• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (c) 2022 Google LLC.
7  * Copyright (c) 2022 LunarG, Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Tests for VK_EXT_host_image_copy
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktImageHostImageCopyTests.hpp"
27 
28 #include "vktTestCase.hpp"
29 #include "vktTestGroupUtil.hpp"
30 
31 #include "vkCmdUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkBarrierUtil.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkImageWithMemory.hpp"
40 #include "vkBufferWithMemory.hpp"
41 #include "vktImageTestsUtil.hpp"
42 #include "ycbcr/vktYCbCrUtil.hpp"
43 
44 #include "tcuTestLog.hpp"
45 
46 namespace vkt
47 {
48 namespace image
49 {
50 namespace
51 {
52 
53 using namespace vk;
54 
getAspectFlags(vk::VkFormat format)55 vk::VkImageAspectFlags getAspectFlags (vk::VkFormat format)
56 {
57 	if (isCompressedFormat(format))
58 	{
59 		return vk::VK_IMAGE_ASPECT_COLOR_BIT;
60 	}
61 
62 	const auto	sampledFormat	= mapVkFormat(format);
63 	if (sampledFormat.order == tcu::TextureFormat::S)
64 	{
65 		return vk::VK_IMAGE_ASPECT_STENCIL_BIT;
66 	}
67 	if (sampledFormat.order == tcu::TextureFormat::D || sampledFormat.order == tcu::TextureFormat::DS)
68 	{
69 		return vk::VK_IMAGE_ASPECT_DEPTH_BIT;
70 	}
71 	return vk::VK_IMAGE_ASPECT_COLOR_BIT;
72 }
73 
getChannelSize(vk::VkFormat format)74 deUint32 getChannelSize (vk::VkFormat format)
75 {
76 	const auto tcuFormat = isCompressedFormat(format) ? tcu::getUncompressedFormat(mapVkCompressedFormat(format)) : mapVkFormat(format);
77 	if (tcuFormat.order != tcu::TextureFormat::D && tcuFormat.order != tcu::TextureFormat::S && tcuFormat.order != tcu::TextureFormat::DS)
78 	{
79 		return tcu::getChannelSize(tcuFormat.type);
80 	}
81 	switch (format)
82 	{
83 	case vk::VK_FORMAT_D24_UNORM_S8_UINT:
84 		return 4;
85 	case vk::VK_FORMAT_D32_SFLOAT:
86 		return 4;
87 	case vk::VK_FORMAT_D16_UNORM:
88 		return 2;
89 	case vk::VK_FORMAT_S8_UINT:
90 		return 1;
91 	default:
92 		break;
93 	}
94 	DE_ASSERT(0);
95 	return 0;
96 }
97 
getNumChannels(vk::VkFormat format)98 deUint32 getNumChannels (vk::VkFormat format)
99 {
100 	const auto tcuFormat = isCompressedFormat(format) ? tcu::getUncompressedFormat(mapVkCompressedFormat(format)) : mapVkFormat(format);
101 	if (tcuFormat.order != tcu::TextureFormat::D && tcuFormat.order != tcu::TextureFormat::S && tcuFormat.order != tcu::TextureFormat::DS)
102 	{
103 		return tcu::getNumUsedChannels(tcuFormat.order);
104 	}
105 	return 1;
106 }
107 
generateData(void * ptr,deUint32 size,vk::VkFormat format)108 void generateData(void* ptr, deUint32 size, vk::VkFormat format) {
109 	if (isDepthStencilFormat(format))
110 	{
111 		de::Random randomGen(deInt32Hash((deUint32)format) ^
112 							 deInt32Hash((deUint32)size));
113 		if (format == VK_FORMAT_D16_UNORM) {
114 			ycbcr::fillRandomNoNaN(&randomGen, (deUint8*)ptr, size, VK_FORMAT_R16_UNORM);
115 		} else {
116 			ycbcr::fillRandomNoNaN(&randomGen, (deUint8*)ptr, size, VK_FORMAT_R32_SFLOAT);
117 		}
118 	}
119 	else if (isCompressedFormat(format))
120 	{
121 		memset(ptr, 255, size);
122 	}
123 	else
124 	{
125 		de::Random randomGen(deInt32Hash((deUint32)format) ^
126 							 deInt32Hash((deUint32)size));
127 		ycbcr::fillRandomNoNaN(&randomGen, (deUint8*)ptr, size, format);
128 	}
129 }
130 
getHostImageCopyProperties(const vk::InstanceDriver & instanceDriver,VkPhysicalDevice physicalDevice,vk::VkPhysicalDeviceHostImageCopyPropertiesEXT * hostImageCopyProperties)131 void getHostImageCopyProperties(const vk::InstanceDriver& instanceDriver, VkPhysicalDevice physicalDevice, vk::VkPhysicalDeviceHostImageCopyPropertiesEXT* hostImageCopyProperties) {
132 	vk::VkPhysicalDeviceProperties				properties;
133 	deMemset(&properties, 0, sizeof(vk::VkPhysicalDeviceProperties));
134 	vk::VkPhysicalDeviceProperties2				properties2 =
135 	{
136 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,			// VkStructureType					sType
137 		hostImageCopyProperties,									// const void*						pNext
138 		properties													// VkPhysicalDeviceProperties		properties
139 	};
140 	instanceDriver.getPhysicalDeviceProperties2(physicalDevice, &properties2);
141 }
142 
isBlockCompressedFormat(vk::VkFormat format)143 bool isBlockCompressedFormat (vk::VkFormat format)
144 {
145 	switch (format)
146 	{
147 		case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
148 		case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
149 		case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
150 		case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
151 		case VK_FORMAT_BC2_UNORM_BLOCK:
152 		case VK_FORMAT_BC2_SRGB_BLOCK:
153 		case VK_FORMAT_BC3_UNORM_BLOCK:
154 		case VK_FORMAT_BC3_SRGB_BLOCK:
155 		case VK_FORMAT_BC4_UNORM_BLOCK:
156 		case VK_FORMAT_BC4_SNORM_BLOCK:
157 		case VK_FORMAT_BC5_UNORM_BLOCK:
158 		case VK_FORMAT_BC5_SNORM_BLOCK:
159 		case VK_FORMAT_BC6H_UFLOAT_BLOCK:
160 		case VK_FORMAT_BC6H_SFLOAT_BLOCK:
161 		case VK_FORMAT_BC7_UNORM_BLOCK:
162 		case VK_FORMAT_BC7_SRGB_BLOCK:
163 			return true;
164 		default:
165 			break;
166 	}
167 	return false;
168 }
169 
checkSupportedFormatFeatures(const vk::InstanceDriver & vki,VkPhysicalDevice physicalDevice,vk::VkFormat format,vk::VkImageTiling tiling,deUint64 * outDrmModifier)170 void checkSupportedFormatFeatures(const vk::InstanceDriver& vki, VkPhysicalDevice physicalDevice, vk::VkFormat format, vk::VkImageTiling tiling, deUint64 *outDrmModifier)
171 {
172 	vk::VkDrmFormatModifierPropertiesList2EXT drmList = vk::initVulkanStructure();
173 	vk::VkFormatProperties3 formatProperties3 = tiling == vk::VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT ?
174 												vk::initVulkanStructure(&drmList) :
175 												vk::initVulkanStructure();
176 	vk::VkFormatProperties2 formatProperties2 = vk::initVulkanStructure(&formatProperties3);
177 	vki.getPhysicalDeviceFormatProperties2(physicalDevice, format, &formatProperties2);
178 	std::vector<vk::VkDrmFormatModifierProperties2EXT> modifiers(drmList.drmFormatModifierCount);
179 
180 	if (tiling == vk::VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
181 	{
182 		if (drmList.drmFormatModifierCount == 0)
183 			TCU_THROW(NotSupportedError, "Format feature host image transfer not supported for drm format modifier.");
184 		drmList.pDrmFormatModifierProperties = modifiers.data();
185 		vki.getPhysicalDeviceFormatProperties2(physicalDevice, format, &formatProperties2);
186 
187 		bool modifierFound = false;
188 		for (deUint32 i = 0; i < drmList.drmFormatModifierCount; ++i)
189 		{
190 			if (drmList.pDrmFormatModifierProperties[i].drmFormatModifierTilingFeatures & vk::VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT)
191 			{
192 				*outDrmModifier = drmList.pDrmFormatModifierProperties[i].drmFormatModifier;
193 				return;
194 			}
195 		}
196 
197 		if (!modifierFound)
198 			TCU_THROW(NotSupportedError, "Format feature host image transfer not supported for drm format modifier.");
199 	}
200 	else
201 	{
202 		if (tiling == vk::VK_IMAGE_TILING_LINEAR &&
203 			(formatProperties3.linearTilingFeatures & vk::VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0)
204 			TCU_THROW(NotSupportedError, "Format feature host image transfer not supported for optimal tiling.");
205 		if (tiling == vk::VK_IMAGE_TILING_OPTIMAL &&
206 			(formatProperties3.optimalTilingFeatures & vk::VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0)
207 			TCU_THROW(NotSupportedError, "Format feature host image transfer not supported for optimal tiling.");
208 	}
209 }
210 
211 enum Command {
212 	DRAW,
213 	DISPATCH,
214 };
215 
216 struct TestParameters
217 {
218 	bool				hostCopyMemoryToImage;
219 	bool				hostCopyImageToMemory;
220 	bool				hostTransferLayout;
221 	bool				outputImageHostTransition;
222 	bool				memcpyFlag;
223 	bool				dynamicRendering;
224 	Command				command;
225 	vk::VkFormat		imageSampledFormat;
226 	vk::VkImageLayout	srcLayout;
227 	vk::VkImageLayout	dstLayout;
228 	vk::VkImageLayout	intermediateLayout;
229 	vk::VkImageTiling	sampledTiling;
230 	vk::VkFormat		imageOutputFormat;
231 	vk::VkExtent3D		imageSize;
232 	bool				sparse;
233 	deUint32			mipLevel;
234 	deUint32			regionsCount;
235 	deUint32			padding;
236 };
237 
238 class HostImageCopyTestInstance : public vkt::TestInstance
239 {
240 public:
HostImageCopyTestInstance(vkt::Context & context,const TestParameters & parameters)241 	HostImageCopyTestInstance							(vkt::Context& context, const TestParameters& parameters)
242 														: vkt::TestInstance	(context)
243 														, m_parameters		(parameters)
244 														{
245 														}
246 	void						transitionImageLayout	(const Move<vk::VkCommandBuffer>* cmdBuffer, vk::VkImage image, vk::VkImageLayout oldLayout, vk::VkImageLayout newLayout, vk::VkImageSubresourceRange subresourceRange);
247 	void						copyMemoryToImage		(const std::vector<deUint8> testData, vk::VkImage image, deUint32 texelSize, const vk::VkImageSubresourceLayers subresourceLayers, deInt32 xOffset, deInt32 yOffset, deUint32 width, deUint32 height);
248 
249 private:
250 	tcu::TestStatus				iterate					(void);
251 
252 	const TestParameters	m_parameters;
253 };
254 
transitionImageLayout(const Move<vk::VkCommandBuffer> * cmdBuffer,vk::VkImage image,vk::VkImageLayout oldLayout,vk::VkImageLayout newLayout,vk::VkImageSubresourceRange subresourceRange)255 void HostImageCopyTestInstance::transitionImageLayout (const Move<vk::VkCommandBuffer>* cmdBuffer, vk::VkImage image, vk::VkImageLayout oldLayout, vk::VkImageLayout newLayout, vk::VkImageSubresourceRange subresourceRange)
256 {
257 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
258 	const vk::VkDevice				device				= m_context.getDevice();
259 	const vk::VkQueue				queue				= m_context.getUniversalQueue();
260 
261 	if (m_parameters.hostTransferLayout)
262 	{
263 		vk::VkHostImageLayoutTransitionInfoEXT transition =
264 		{
265 			vk::VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,		// VkStructureType			sType;
266 			DE_NULL,															// const void*				pNext;
267 			image,																// VkImage					image;
268 			oldLayout,															// VkImageLayout			oldLayout;
269 			newLayout,															// VkImageLayout			newLayout;
270 			subresourceRange													// VkImageSubresourceRange subresourceRange;
271 		};
272 		vk.transitionImageLayoutEXT(device, 1, &transition);
273 	}
274 	else
275 	{
276 		vk::beginCommandBuffer(vk, **cmdBuffer, 0u);
277 		auto imageMemoryBarrier = makeImageMemoryBarrier(0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, oldLayout, newLayout, image, subresourceRange);
278 		vk.cmdPipelineBarrier(**cmdBuffer, vk::VK_PIPELINE_STAGE_NONE, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1, &imageMemoryBarrier);
279 		vk::endCommandBuffer(vk, **cmdBuffer);
280 		vk::submitCommandsAndWait(vk, device, queue, **cmdBuffer);
281 	}
282 }
283 
copyMemoryToImage(const std::vector<deUint8> testData,vk::VkImage image,deUint32 texelSize,const vk::VkImageSubresourceLayers subresourceLayers,deInt32 xOffset,deInt32 yOffset,deUint32 width,deUint32 height)284 void HostImageCopyTestInstance::copyMemoryToImage (const std::vector<deUint8> testData, vk::VkImage image, deUint32 texelSize, const vk::VkImageSubresourceLayers subresourceLayers, deInt32 xOffset, deInt32 yOffset, deUint32 width, deUint32 height)
285 {
286 	const DeviceInterface&			vk			= m_context.getDeviceInterface();
287 	const vk::VkDevice				device		= m_context.getDevice();
288 	std::vector<deUint8>			data		(texelSize * width * height);
289 	const deUint32					imageWidth	= m_parameters.imageSize.width;
290 	for (deUint32 i = 0; i < height; ++i) {
291 		memcpy(&data[i * width * texelSize], &testData[((yOffset + i) * imageWidth + xOffset) * texelSize], width * texelSize);
292 	}
293 
294 	const deUint32 regionsCount = m_parameters.regionsCount > height ? m_parameters.regionsCount : 1u;
295 	std::vector<vk::VkMemoryToImageCopyEXT> regions;
296 
297 	for (deUint32 i = 0; i < regionsCount; ++i)
298 	{
299 		vk::VkOffset3D	offset = { xOffset, (deInt32)(yOffset + height / regionsCount * i), 0 };
300 		vk::VkExtent3D	extent = { width, height / regionsCount, 1 };
301 		if (i == regionsCount - 1)
302 			extent.height = height - height / regionsCount * i;
303 
304 		if (extent.height == 0)
305 			continue;
306 
307 		deUint32 dataOffset = width * (height / regionsCount * i) * texelSize;
308 
309 		const vk::VkMemoryToImageCopyEXT region = {
310 			vk::VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,		// VkStructureType				sType;
311 			DE_NULL,											// const void*					pNext;
312 			&data[dataOffset],									// const void*					memoryHostPointer;
313 			0,													// uint32_t						memoryRowLength;
314 			0,													// uint32_t						memoryImageHeight;
315 			subresourceLayers,									// VkImageSubresourceLayers		imageSubresource;
316 			offset,												// VkOffset3D					imageOffset;
317 			extent												// VkExtent3D					imageExtent;
318 		};
319 		regions.push_back(region);
320 	}
321 
322 	vk::VkCopyMemoryToImageInfoEXT copyMemoryToImageInfo =
323 	{
324 		vk::VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT,	// VkStructureType					sType;
325 		DE_NULL,												// const void*						pNext;
326 		0u,														// VkMemoryImageCopyFlagsEXT		flags;
327 		image,													// VkImage							dstImage;
328 		m_parameters.dstLayout,									// VkImageLayout					dstImageLayout;
329 		(deUint32)regions.size(),								// uint32_t							regionCount;
330 		regions.data(),											// const VkMemoryToImageCopyEXT*	pRegions;
331 	};
332 
333 	vk.copyMemoryToImageEXT(device, &copyMemoryToImageInfo);
334 }
335 
iterate(void)336 tcu::TestStatus HostImageCopyTestInstance::iterate (void)
337 {
338 	const InstanceInterface&			vki					= m_context.getInstanceInterface();
339 	const DeviceInterface&				vk					= m_context.getDeviceInterface();
340 	const vk::VkPhysicalDevice			physicalDevice		= m_context.getPhysicalDevice();
341 	const vk::VkDevice					device				= m_context.getDevice();
342 	const auto&							deviceExtensions	= m_context.getDeviceExtensions();
343 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
344 	const vk::VkQueue					queue				= m_context.getUniversalQueue();
345 	auto&								alloc				= m_context.getDefaultAllocator();
346 	tcu::TestLog&						log					= m_context.getTestContext().getLog();
347 
348 	std::stringstream					commandsLog;
349 
350 	const Move<vk::VkCommandPool>		cmdPool				(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
351 	const Move<vk::VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
352 
353 	const vk::VkExtent3D				imageSize			= { m_parameters.imageSize.width * (deUint32)dePow(2, m_parameters.mipLevel), m_parameters.imageSize.height * (deUint32)dePow(2, m_parameters.mipLevel), 1 };
354 	const vk::VkExtent3D				mipImageSize		= { m_parameters.imageSize.width, m_parameters.imageSize.height, 1 };
355 
356 	const vk::VkRect2D					renderArea			= vk::makeRect2D(0, 0, mipImageSize.width, mipImageSize.height);
357 
358 	const auto							sampledChannelSize	= getChannelSize(m_parameters.imageSampledFormat);
359 	const auto							sampledNumChannels	= getNumChannels(m_parameters.imageSampledFormat);
360 	const auto							sampledBufferCount	= mipImageSize.width * mipImageSize.height * sampledNumChannels;
361 	const auto							sampledBufferSize	= sampledBufferCount * sampledChannelSize;
362 
363 	const auto							outputFormat		= mapVkFormat(m_parameters.imageOutputFormat);
364 	const auto							outputChannelSize	= getChannelSize(m_parameters.imageOutputFormat);
365 	const auto							outputNumChannels	= getNumUsedChannels(m_parameters.imageOutputFormat);
366 	const auto							outputBufferCount	= mipImageSize.width * mipImageSize.height * outputNumChannels;
367 	const auto							outputBufferSize	= outputBufferCount * outputChannelSize;
368 
369 	vk::VkImage							sampledImage;
370 	de::MovePtr<ImageWithMemory>		sampledImageWithMemory;
371 	de::MovePtr<SparseImage>			sparseSampledImage;
372 	de::MovePtr<ImageWithMemory>		sampledImageWithMemoryCopy;
373 	de::MovePtr<ImageWithMemory>		outputImage;
374 	Move<vk::VkImageView>				sampledImageView;
375 	Move<vk::VkImageView>				sampledImageViewCopy;
376 	Move<vk::VkImageView>				outputImageView;
377 
378 	const vk::VkImageAspectFlags		sampledAspect				= getAspectFlags(m_parameters.imageSampledFormat);
379 	const vk::VkComponentMapping		componentMapping			= makeComponentMappingRGBA();
380 	const vk::VkOffset3D				imageOffset					= makeOffset3D(0, 0, 0);
381 	const vk::VkImageSubresource		sampledSubresource			= makeImageSubresource(sampledAspect, m_parameters.mipLevel, 0u);
382 	const vk::VkImageSubresourceRange	sampledSubresourceRange		= makeImageSubresourceRange(sampledAspect, m_parameters.mipLevel, 1u, 0u, 1u);
383 	const vk::VkImageSubresourceLayers	sampledSubresourceLayers	= makeImageSubresourceLayers(sampledAspect, m_parameters.mipLevel, 0u, 1u);
384 	const auto							outputSubresourceRange		= makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, m_parameters.mipLevel, 1u, 0u, 1u);
385 	const vk::VkImageSubresourceLayers	outputSubresourceLayers		= makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, m_parameters.mipLevel, 0u, 1u);
386 
387 	std::vector<deUint8>				testData					(sampledBufferSize);
388 	generateData(testData.data(), sampledBufferSize, m_parameters.imageSampledFormat);
389 
390 	// Create sampled image
391 	{
392 		vk::VkImageUsageFlags	usage = vk::VK_IMAGE_USAGE_SAMPLED_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
393 		if (m_parameters.hostCopyMemoryToImage || m_parameters.hostCopyImageToMemory || m_parameters.memcpyFlag || m_parameters.hostTransferLayout)
394 			usage |= vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
395 		if (m_parameters.intermediateLayout == vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
396 			usage |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
397 		else if (m_parameters.intermediateLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
398 			usage |= vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
399 		else if (m_parameters.intermediateLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
400 			usage |= vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
401 
402 		vk::VkImageCreateInfo	createInfo =
403 		{
404 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
405 			DE_NULL,									// const void*				pNext
406 			0u,											// VkImageCreateFlags		flags
407 			vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType
408 			m_parameters.imageSampledFormat,			// VkFormat					format
409 			imageSize,									// VkExtent3D				extent
410 			m_parameters.mipLevel + 1,					// uint32_t					mipLevels
411 			1u,											// uint32_t					arrayLayers
412 			vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
413 			m_parameters.sampledTiling,					// VkImageTiling			tiling
414 			usage,										// VkImageUsageFlags		usage
415 			vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
416 			0,											// uint32_t					queueFamilyIndexCount
417 			DE_NULL,									// const uint32_t*			pQueueFamilyIndices
418 			vk::VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout
419 		};
420 
421 		if (m_parameters.sparse)
422 		{
423 			createInfo.flags |= (vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT | vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT);
424 			sparseSampledImage = de::MovePtr<SparseImage>(new SparseImage(vk, device, physicalDevice, vki, createInfo, m_context.getSparseQueue(), alloc, mapVkFormat(createInfo.format)));
425 			sampledImage = **sparseSampledImage;
426 		}
427 		else
428 		{
429 			sampledImageWithMemory = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
430 			if (m_parameters.memcpyFlag)
431 				sampledImageWithMemoryCopy = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
432 			sampledImage = **sampledImageWithMemory;
433 		}
434 
435 		vk::VkImageViewCreateInfo		imageViewCreateInfo =
436 		{
437 			vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
438 			DE_NULL,										// const void*				pNext;
439 			(vk::VkImageViewCreateFlags)0u,					// VkImageViewCreateFlags	flags;
440 			sampledImage,									// VkImage					image;
441 			vk::VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
442 			m_parameters.imageSampledFormat,				// VkFormat					format;
443 			componentMapping,								// VkComponentMapping		components;
444 			sampledSubresourceRange							// VkImageSubresourceRange	subresourceRange;
445 		};
446 		sampledImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
447 		if (m_parameters.memcpyFlag)
448 		{
449 			imageViewCreateInfo.image = **sampledImageWithMemoryCopy;
450 			sampledImageViewCopy = createImageView(vk, device, &imageViewCreateInfo, NULL);;
451 		}
452 	}
453 
454 	// Create output image
455 	{
456 		vk::VkImageUsageFlags	usage = vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
457 		if (m_parameters.outputImageHostTransition || m_parameters.hostCopyImageToMemory || m_parameters.hostTransferLayout)
458 			usage |= vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
459 		if (m_parameters.command == DISPATCH)
460 			usage |= vk::VK_IMAGE_USAGE_STORAGE_BIT;
461 
462 		const vk::VkImageCreateInfo	createInfo		=
463 		{
464 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
465 			DE_NULL,									// const void*				pNext
466 			0u,											// VkImageCreateFlags		flags
467 			vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType
468 			m_parameters.imageOutputFormat,				// VkFormat					format
469 			imageSize,									// VkExtent3D				extent
470 			m_parameters.mipLevel + 1,					// uint32_t					mipLevels
471 			1u,											// uint32_t					arrayLayers
472 			vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
473 			vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling
474 			usage,										// VkImageUsageFlags		usage
475 			vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
476 			0,											// uint32_t					queueFamilyIndexCount
477 			DE_NULL,									// const uint32_t*			pQueueFamilyIndices
478 			vk::VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout
479 		};
480 
481 		outputImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
482 
483 		vk::VkImageViewCreateInfo		imageViewCreateInfo =
484 		{
485 			vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
486 			DE_NULL,										// const void*				pNext;
487 			(VkImageViewCreateFlags)0u,						// VkImageViewCreateFlags	flags;
488 			**outputImage,									// VkImage					image;
489 			vk::VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
490 			m_parameters.imageOutputFormat,					// VkFormat					format;
491 			componentMapping,								// VkComponentMapping		components;
492 			outputSubresourceRange							// VkImageSubresourceRange	subresourceRange;
493 		};
494 		outputImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
495 	}
496 
497 	const vk::VkAttachmentDescription	colorAttachmentDescription	=
498 	{
499 			(vk::VkAttachmentDescriptionFlags)0u,		// VkAttachmentDescriptionFlags    flags
500 			m_parameters.imageOutputFormat,				// VkFormat                        format
501 			vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits           samples
502 			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,		// VkAttachmentLoadOp              loadOp
503 			vk::VK_ATTACHMENT_STORE_OP_STORE,			// VkAttachmentStoreOp             storeOp
504 			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,		// VkAttachmentLoadOp              stencilLoadOp
505 			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,		// VkAttachmentStoreOp             stencilStoreOp
506 			vk::VK_IMAGE_LAYOUT_GENERAL,				// VkImageLayout                   initialLayout
507 			vk::VK_IMAGE_LAYOUT_GENERAL					// VkImageLayout                   finalLayout
508 	};
509 
510 	const vk::VkAttachmentReference				colorAttachmentRef =
511 	{
512 		0u,								// deUint32         attachment
513 		vk::VK_IMAGE_LAYOUT_GENERAL		// VkImageLayout    layout
514 	};
515 
516 	const vk::VkSubpassDescription				subpassDescription =
517 	{
518 		(vk::VkSubpassDescriptionFlags)0u,						// VkSubpassDescriptionFlags       flags
519 		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint             pipelineBindPoint
520 		0u,														// deUint32                        inputAttachmentCount
521 		DE_NULL,												// const VkAttachmentReference*    pInputAttachments
522 		1u,														// deUint32                        colorAttachmentCount
523 		&colorAttachmentRef,									// const VkAttachmentReference*    pColorAttachments
524 		DE_NULL,												// const VkAttachmentReference*    pResolveAttachments
525 		DE_NULL,												// const VkAttachmentReference*    pDepthStencilAttachment
526 		0u,														// deUint32                        preserveAttachmentCount
527 		DE_NULL													// const deUint32*                 pPreserveAttachments
528 	};
529 
530 	Move<vk::VkRenderPass>				renderPass;
531 	Move<vk::VkFramebuffer>				framebuffer;
532 	if (!m_parameters.dynamicRendering && m_parameters.command == DRAW)
533 	{
534 		const vk::VkRenderPassCreateInfo renderPassInfo =
535 		{
536 			vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
537 			nullptr,										// const void*						pNext;
538 			0u,												// VkRenderPassCreateFlags			flags;
539 			1u,												// deUint32							attachmentCount;
540 			&colorAttachmentDescription,					// const VkAttachmentDescription*	pAttachments;
541 			1u,												// deUint32							subpassCount;
542 			&subpassDescription,							// const VkSubpassDescription*		pSubpasses;
543 			0u,												// deUint32							dependencyCount;
544 			nullptr,										// const VkSubpassDependency*		pDependencies;
545 		};
546 		renderPass	= createRenderPass(vk, device, &renderPassInfo);
547 		framebuffer = makeFramebuffer(vk, device, *renderPass, *outputImageView, renderArea.extent.width, renderArea.extent.height);
548 	}
549 
550 	const std::vector<vk::VkViewport>	viewports			{ makeViewport(renderArea.extent) };
551 	const std::vector<vk::VkRect2D>		scissors			{ makeRect2D(renderArea.extent) };
552 
553 	vk::ShaderWrapper			vert				= vk::ShaderWrapper(vk, device, m_context.getBinaryCollection().get("vert"));
554 	vk::ShaderWrapper			frag				= vk::ShaderWrapper(vk, device, m_context.getBinaryCollection().get("frag"));
555 
556 	DescriptorSetLayoutBuilder			descriptorBuilder;
557 	descriptorBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_FRAGMENT_BIT | vk::VK_SHADER_STAGE_COMPUTE_BIT);
558 	if (m_parameters.command == DISPATCH)
559 		descriptorBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
560 
561 	const auto							descriptorSetLayout	(descriptorBuilder.build(vk, device));
562 	const vk::PipelineLayoutWrapper		pipelineLayout		(PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC, vk, device, *descriptorSetLayout);
563 
564 	DescriptorPoolBuilder				poolBuilder;
565 	poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
566 	if (m_parameters.command == DISPATCH)
567 		poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
568 	const Move<vk::VkDescriptorPool>	descriptorPool		= poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
569 	const Move<vk::VkDescriptorSet>		descriptorSet		(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
570 
571 	vk::VkSamplerCreateInfo				samplerParams		=
572 	{
573 		vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType		sType;
574 		DE_NULL,										// const void*			pNext;
575 		0u,												// VkSamplerCreateFlags	flags;
576 		vk::VK_FILTER_NEAREST,							// VkFilter				magFilter;
577 		vk::VK_FILTER_NEAREST,							// VkFilter				minFilter;
578 		vk::VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode	mipmapMode;
579 		vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,	// VkSamplerAddressMode	addressModeU;
580 		vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,	// VkSamplerAddressMode	addressModeV;
581 		vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,	// VkSamplerAddressMode	addressModeW;
582 		0.0f,											// float				mipLodBias;
583 		VK_FALSE,										// VkBool32				anisotropyEnable;
584 		0.0f,											// float				maxAnisotropy;
585 		VK_FALSE,										// VkBool32				compareEnable;
586 		vk::VK_COMPARE_OP_NEVER,						// VkCompareOp			compareOp;
587 		0.0f,											// float				minLod;
588 		VK_LOD_CLAMP_NONE,								// float				maxLod;
589 		vk::VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,			// VkBorderColor		borderColor;
590 		VK_FALSE										// VkBool32				unnormalizedCoordinates;
591 	};
592 	const vk::Move<vk::VkSampler>		sampler					= createSampler(vk, device, &samplerParams);
593 	vk::VkDescriptorImageInfo			descriptorSrcImageInfo	(makeDescriptorImageInfo(*sampler, *sampledImageView, vk::VK_IMAGE_LAYOUT_GENERAL));
594 	const vk::VkDescriptorImageInfo		descriptorDstImageInfo	(makeDescriptorImageInfo(*sampler, *outputImageView, vk::VK_IMAGE_LAYOUT_GENERAL));
595 
596 	const vk::VkPipelineVertexInputStateCreateInfo vertexInput =
597 	{
598 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
599 		nullptr,														//	const void*									pNext;
600 		0u,																//	VkPipelineVertexInputStateCreateFlags		flags;
601 		0u,																//	deUint32									vertexBindingDescriptionCount;
602 		DE_NULL,														//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
603 		0u,																//	deUint32									vertexAttributeDescriptionCount;
604 		DE_NULL,														//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
605 	};
606 
607 	GraphicsPipelineWrapper	pipeline(vki, vk, physicalDevice, device, deviceExtensions, vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
608 	Move<vk::VkPipeline>	computePipeline;
609 
610 	if (m_parameters.command == DRAW)
611 	{
612 		vk::VkPipelineRenderingCreateInfo		pipelineRenderingCreateInfo;
613 		if (m_parameters.dynamicRendering)
614 		{
615 			pipelineRenderingCreateInfo = {
616 				vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,	// VkStructureType	sType
617 				DE_NULL,												// const void*		pNext
618 				0u,														// uint32_t			viewMask
619 				1u,														// uint32_t			colorAttachmentCount
620 				&m_parameters.imageOutputFormat,						// const VkFormat*	pColorAttachmentFormats
621 				vk::VK_FORMAT_UNDEFINED,								// VkFormat			depthAttachmentFormat
622 				vk::VK_FORMAT_UNDEFINED									// VkFormat			stencilAttachmentFormat
623 			};
624 		}
625 
626 		vk::PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
627 		renderingCreateInfoWrapper.ptr = m_parameters.dynamicRendering ? &pipelineRenderingCreateInfo : DE_NULL;
628 
629 		pipeline.setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
630 			.setDefaultRasterizationState()
631 			.setDefaultMultisampleState()
632 			.setDefaultDepthStencilState()
633 			.setDefaultColorBlendState()
634 			.setupVertexInputState(&vertexInput)
635 			.setupPreRasterizationShaderState(viewports,
636 				scissors,
637 				pipelineLayout,
638 				*renderPass,
639 				0u,
640 				vert,
641 				DE_NULL,
642 				{},
643 				{},
644 				{},
645 				DE_NULL,
646 				DE_NULL,
647 				renderingCreateInfoWrapper)
648 			.setupFragmentShaderState(pipelineLayout, *renderPass, 0u, frag)
649 			.setupFragmentOutputState(*renderPass)
650 			.setMonolithicPipelineLayout(pipelineLayout)
651 			.buildPipeline();
652 	}
653 	else
654 	{
655 		const Unique<vk::VkShaderModule> cs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0u));
656 		const vk::VkPipelineShaderStageCreateInfo	pipelineShaderStageParams =
657 		{
658 			vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// sType
659 			DE_NULL,													// pNext
660 			(VkPipelineShaderStageCreateFlags)0u,						// flags
661 			vk::VK_SHADER_STAGE_COMPUTE_BIT,							// stage
662 			*cs,														// module
663 			"main",														// pName
664 			DE_NULL,													// pSpecializationInfo
665 		};
666 		const vk::VkComputePipelineCreateInfo		pipelineCreateInfo =
667 		{
668 			vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// sType
669 			DE_NULL,													// pNext
670 			(VkPipelineCreateFlags)0u,									// flags
671 			pipelineShaderStageParams,									// stage
672 			*pipelineLayout,											// layout
673 			DE_NULL,													// basePipelineHandle
674 			0,															// basePipelineIndex
675 		};
676 		computePipeline = createComputePipeline(vk, device, DE_NULL, &pipelineCreateInfo);
677 	}
678 
679 	de::MovePtr<BufferWithMemory>	colorOutputBuffer		= de::MovePtr<BufferWithMemory>(new BufferWithMemory(
680 		vk, device, alloc, makeBufferCreateInfo(outputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
681 
682 	// Load sampled image
683 	if (m_parameters.hostCopyMemoryToImage)
684 	{
685 		transitionImageLayout(&cmdBuffer, sampledImage, vk::VK_IMAGE_LAYOUT_UNDEFINED, m_parameters.dstLayout, sampledSubresourceRange);
686 		commandsLog << "vkTransitionImageLayoutEXT() image " << sampledImage << " to layout " << getImageLayoutStr(m_parameters.dstLayout).toString() << "\n";
687 
688 		copyMemoryToImage(testData, sampledImage, sampledChannelSize * sampledNumChannels, sampledSubresourceLayers, 0, 0, mipImageSize.width, mipImageSize.height);
689 		commandsLog << "vkCopyMemoryToImageEXT() with image " << sampledImage << ", xOffset (0), yOffset (0), width (" << mipImageSize.width << "), height (" << mipImageSize.height << ")\n";
690 
691 		de::Random randomGen(deInt32Hash((deUint32)m_parameters.imageSampledFormat) ^
692 							 deInt32Hash((deUint32)mipImageSize.width) ^
693 							 deInt32Hash((deUint32)mipImageSize.height) ^
694 							 deInt32Hash((deUint32)mipImageSize.depth));
695 		for (int i = 0; i < 20; ++i)
696 		{
697 			deInt32 xOffset = randomGen.getInt32() % (mipImageSize.width / 2);
698 			deInt32 yOffset = randomGen.getInt32() % (mipImageSize.height / 2);
699 			deUint32 width = deMaxu32(randomGen.getUint32() % (mipImageSize.width / 2), 1u);
700 			deUint32 height = deMaxu32(randomGen.getUint32() % (mipImageSize.height / 2), 1u);
701 
702 			if (isCompressedFormat(m_parameters.imageSampledFormat)) {
703 				deUint32 blockWidth		= getBlockWidth(m_parameters.imageSampledFormat);
704 				deUint32 blockHeight	= getBlockHeight(m_parameters.imageSampledFormat);
705 				xOffset = (xOffset / blockWidth) * blockWidth;
706 				yOffset = (yOffset / blockHeight) * blockHeight;
707 				width	= deMaxu32((width / blockWidth) * blockWidth, blockWidth);
708 				height	= deMaxu32((height / blockHeight) * blockHeight, blockHeight);
709 			}
710 
711 			copyMemoryToImage(testData, sampledImage, sampledChannelSize * sampledNumChannels, sampledSubresourceLayers, xOffset, yOffset, width, height);
712 			commandsLog << "vkCopyMemoryToImageEXT() with image " << sampledImage << ", xOffset (" << xOffset << "), yOffset (" << yOffset << "), width (" << width << "), height (" << height << ")\n";
713 		}
714 
715 		if (m_parameters.dstLayout != vk::VK_IMAGE_LAYOUT_GENERAL)
716 		{
717 			transitionImageLayout(&cmdBuffer, sampledImage, m_parameters.dstLayout, vk::VK_IMAGE_LAYOUT_GENERAL, sampledSubresourceRange);
718 			commandsLog << "vkTransitionImageLayoutEXT() image " << sampledImage << " to layout VK_IMAGE_LAYOUT_GENERAL\n";
719 		}
720 	}
721 	else
722 	{
723 		de::MovePtr<BufferWithMemory> sampledBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, alloc, makeBufferCreateInfo(sampledBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::HostVisible));
724 
725 		auto& bufferAlloc = sampledBuffer->getAllocation();
726 		memcpy(bufferAlloc.getHostPtr(), testData.data(), sampledBufferSize);
727 		flushAlloc(vk, device, bufferAlloc);
728 
729 		transitionImageLayout(&cmdBuffer, sampledImage, vk::VK_IMAGE_LAYOUT_UNDEFINED, m_parameters.dstLayout, sampledSubresourceRange);
730 		commandsLog << "vkTransitionImageLayoutEXT() image " << sampledImage << " to layout" << getImageLayoutStr(m_parameters.dstLayout).toString() << "\n";
731 
732 		vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
733 		const vk::VkBufferImageCopy copyRegion =
734 		{
735 			0,
736 			0,
737 			0,
738 			sampledSubresourceLayers,
739 			imageOffset,
740 			{
741 				mipImageSize.width,
742 				mipImageSize.height,
743 				mipImageSize.depth,
744 			},
745 		};
746 		vk.cmdCopyBufferToImage(*cmdBuffer, sampledBuffer->get(), sampledImage, m_parameters.dstLayout, 1u, &copyRegion);
747 		commandsLog << "vkCmdCopyBufferToImage() with image " << sampledImage << ", xOffset (" << copyRegion.imageOffset.x << "), yOffset (" << copyRegion.imageOffset.y << "), width (" << mipImageSize.width << "), height (" << mipImageSize.height << ")\n";
748 
749 		{
750 			auto		imageMemoryBarrier	= makeImageMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, m_parameters.dstLayout, m_parameters.intermediateLayout, sampledImage, sampledSubresourceRange);
751 			vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1, &imageMemoryBarrier);
752 		}
753 
754 		vk::endCommandBuffer(vk, *cmdBuffer);
755 		deUint32				semaphoreCount	= 0;
756 		vk::VkSemaphore			semaphore		= DE_NULL;
757 		VkPipelineStageFlags	waitStages		= 0;
758 		if (m_parameters.sparse)
759 		{
760 			semaphoreCount = 1;
761 			semaphore = sparseSampledImage->getSemaphore();
762 			waitStages = vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
763 		}
764 		vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer, false, 1u, semaphoreCount, &semaphore, &waitStages);
765 
766 		if (m_parameters.intermediateLayout != vk::VK_IMAGE_LAYOUT_GENERAL)
767 		{
768 			transitionImageLayout(&cmdBuffer, sampledImage, m_parameters.intermediateLayout, vk::VK_IMAGE_LAYOUT_GENERAL, sampledSubresourceRange);
769 			commandsLog << "vkTransitionImageLayoutEXT() image " << sampledImage << " to layout VK_IMAGE_LAYOUT_GENERAL\n";
770 		}
771 	}
772 
773 	if (m_parameters.memcpyFlag)
774 	{
775 		vk::VkImageSubresource2EXT			subresource2 =
776 		{
777 			vk::VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT,	// VkStructureType		sType;
778 			DE_NULL,										// void*				pNext;
779 			sampledSubresource								// VkImageSubresource	imageSubresource;
780 		};
781 
782 		vk::VkSubresourceHostMemcpySizeEXT	subresourceHostMemcpySize	= vk::initVulkanStructure();
783 		vk::VkSubresourceLayout2EXT			subresourceLayout			= vk::initVulkanStructure(&subresourceHostMemcpySize);
784 		vk.getImageSubresourceLayout2KHR(device, sampledImage, &subresource2, &subresourceLayout);
785 
786 		std::vector<deUint8> data((size_t)subresourceHostMemcpySize.size);
787 
788 		const vk::VkImageToMemoryCopyEXT region =
789 		{
790 			vk::VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT,	// VkStructureType				sType;
791 			DE_NULL,										// const void*					pNext;
792 			data.data(),									// void*						memoryHostPointer;
793 			0u,												// uint32_t						memoryRowLength;
794 			0u,												// uint32_t						memoryImageHeight;
795 			sampledSubresourceLayers,						// VkImageSubresourceLayers		imageSubresource;
796 			imageOffset,									// VkOffset3D					imageOffset;
797 			mipImageSize,									// VkExtent3D					imageExtent;
798 		};
799 
800 		const vk::VkCopyImageToMemoryInfoEXT copyImageToMemoryInfo =
801 		{
802 			vk::VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT,	// VkStructureType					sType;
803 			DE_NULL,												// const void*						pNext;
804 			vk::VK_HOST_IMAGE_COPY_MEMCPY_EXT,						// VkMemoryImageCopyFlagsEXT		flags;
805 			sampledImage,											// VkImage							srcImage;
806 			vk::VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout					srcImageLayout;
807 			1,														// uint32_t							regionCount;
808 			&region,												// const VkImageToMemoryCopyEXT*	pRegions;
809 		};
810 		vk.copyImageToMemoryEXT(device, &copyImageToMemoryInfo);
811 		commandsLog << "vkCopyImageToMemoryEXT() with image " << sampledImage << ", xOffset (" << region.imageOffset.x << "), yOffset (" << region.imageOffset.y << "), width (" << mipImageSize.width << "), height (" << mipImageSize.height << ")\n";
812 
813 		transitionImageLayout(&cmdBuffer, **sampledImageWithMemoryCopy, vk::VK_IMAGE_LAYOUT_UNDEFINED, m_parameters.dstLayout, sampledSubresourceRange);
814 
815 		const vk::VkMemoryToImageCopyEXT toImageRegion = {
816 			vk::VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,		// VkStructureType				sType;
817 			DE_NULL,											// const void*					pNext;
818 			data.data(),										// const void*					memoryHostPointer;
819 			0,													// uint32_t						memoryRowLength;
820 			0,													// uint32_t						memoryImageHeight;
821 			sampledSubresourceLayers,							// VkImageSubresourceLayers		imageSubresource;
822 			imageOffset,										// VkOffset3D					imageOffset;
823 			mipImageSize										// VkExtent3D					imageExtent;
824 		};
825 
826 		vk::VkCopyMemoryToImageInfoEXT copyMemoryToImageInfo =
827 		{
828 			vk::VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT,	// VkStructureType					sType;
829 			DE_NULL,												// const void*						pNext;
830 			vk::VK_HOST_IMAGE_COPY_MEMCPY_EXT,						// VkMemoryImageCopyFlagsEXT		flags;
831 			**sampledImageWithMemoryCopy,							// VkImage							dstImage;
832 			m_parameters.dstLayout,									// VkImageLayout					dstImageLayout;
833 			1u,														// uint32_t							regionCount;
834 			&toImageRegion,											// const VkMemoryToImageCopyEXT*	pRegions;
835 		};
836 		vk.copyMemoryToImageEXT(device, &copyMemoryToImageInfo);
837 		commandsLog << "vkCopyMemoryToImageEXT() with image " << **sampledImageWithMemoryCopy << ", xOffset (" << toImageRegion.imageOffset.x << "), yOffset (" << toImageRegion.imageOffset.y << "), width (" << toImageRegion.imageExtent.width << "), height (" << toImageRegion.imageExtent.height << ")\n";
838 		descriptorSrcImageInfo.imageView = *sampledImageViewCopy;
839 
840 		transitionImageLayout(&cmdBuffer, **sampledImageWithMemoryCopy, m_parameters.dstLayout, vk::VK_IMAGE_LAYOUT_GENERAL, sampledSubresourceRange);
841 	}
842 
843 	// Transition output image
844 	transitionImageLayout(&cmdBuffer, **outputImage, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, outputSubresourceRange);
845 	commandsLog << "vkTransitionImageLayoutEXT() image " << **outputImage << " to layout VK_IMAGE_LAYOUT_GENERAL\n";
846 	vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
847 
848 	vk::DescriptorSetUpdateBuilder		updateBuilder;
849 	updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorSrcImageInfo);
850 	if (m_parameters.command == DISPATCH)
851 		updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo);
852 	updateBuilder.update(vk, device);
853 
854 	if (m_parameters.command == DRAW)
855 	{
856 		if (m_parameters.dynamicRendering)
857 			beginRendering(vk, *cmdBuffer, *outputImageView, renderArea, vk::VkClearValue(), vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE);
858 		else
859 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea);
860 
861 		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
862 		vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1, &*descriptorSet, 0, DE_NULL);
863 		vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
864 		commandsLog << "vkCmdDraw()\n";
865 
866 		if (m_parameters.dynamicRendering)
867 			endRendering(vk, *cmdBuffer);
868 		else
869 			endRenderPass(vk, *cmdBuffer);
870 
871 		const auto	postImageBarrier = makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, m_parameters.srcLayout, **outputImage, outputSubresourceRange);
872 		vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
873 	}
874 	else
875 	{
876 		const auto	imageMemoryBarrier	= makeImageMemoryBarrier(0u, vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, **outputImage, outputSubresourceRange);
877 		vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageMemoryBarrier);
878 		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
879 		vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1, &*descriptorSet, 0, DE_NULL);
880 		vk.cmdDispatch(*cmdBuffer, renderArea.extent.width, renderArea.extent.height, 1);
881 		commandsLog << "vkCmdDispatch()\n";
882 
883 		vk::VkImageMemoryBarrier postImageBarrier =
884 		{
885 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType
886 			DE_NULL,										// const void*				pNext
887 			vk::VK_ACCESS_SHADER_WRITE_BIT,					// VkAccessFlags			srcAccessMask
888 			vk::VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask
889 			vk::VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			oldLayout
890 			m_parameters.srcLayout,							// VkImageLayout			newLayout
891 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t					srcQueueFamilyIndex
892 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t					dstQueueFamilyIndex
893 			**outputImage,									// VkImage					image
894 			outputSubresourceRange							// VkImageSubresourceRange	subresourceRange
895 		};
896 
897 		vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
898 	}
899 
900 	const vk::VkBufferImageCopy	copyRegion =
901 	{
902 		0u,																		// VkDeviceSize				bufferOffset;
903 		0u,																		// deUint32					bufferRowLength;
904 		0u,																		// deUint32					bufferImageHeight;
905 		outputSubresourceLayers,												// VkImageSubresourceLayers	imageSubresource;
906 		imageOffset,															// VkOffset3D				imageOffset;
907 		{renderArea.extent.width, renderArea.extent.height, 1}					// VkExtent3D				imageExtent;
908 	};
909 	vk.cmdCopyImageToBuffer(*cmdBuffer, **outputImage, m_parameters.srcLayout, **colorOutputBuffer, 1u, &copyRegion);
910 	commandsLog << "vkCmdCopyImageToBuffer() with image " << **outputImage << ", xOffset (" << imageOffset.x << "), yOffset (" << imageOffset.y << "), width (" << renderArea.extent.width << "), height (" << renderArea.extent.height << "\n";
911 	vk::endCommandBuffer(vk, *cmdBuffer);
912 
913 	vk::submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
914 
915 	// Verify image
916 	tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(outputFormat, renderArea.extent.width, renderArea.extent.height, 1, (const void*)colorOutputBuffer->getAllocation().getHostPtr());
917 
918 	if (m_parameters.hostCopyImageToMemory)
919 	{
920 		const deUint32			paddedBufferSize	= (mipImageSize.width + m_parameters.padding) * (mipImageSize.height + m_parameters.padding) * outputNumChannels * outputChannelSize;
921 		const deUint32			memoryRowLength		= (mipImageSize.width + m_parameters.padding);
922 		const deUint32			memoryImageHeight	= (mipImageSize.height + m_parameters.padding);
923 		std::vector<deUint8>	paddedData			(paddedBufferSize);
924 		std::vector<deUint8>	data				(outputBufferSize);
925 
926 		std::vector<vk::VkImageToMemoryCopyEXT> regions(m_parameters.regionsCount);
927 
928 		for (deUint32 i = 0; i < m_parameters.regionsCount; ++i)
929 		{
930 			vk::VkOffset3D	offset	= { 0, (deInt32)(mipImageSize.height / m_parameters.regionsCount * i), 0 };
931 			vk::VkExtent3D	extent	= { mipImageSize.width, mipImageSize.height / m_parameters.regionsCount, 1 };
932 			if (i == m_parameters.regionsCount - 1)
933 				extent.height = mipImageSize.height - mipImageSize.height / m_parameters.regionsCount * i;
934 
935 			deUint32 dataOffset = (mipImageSize.width + m_parameters.padding) * offset.y * outputNumChannels * outputChannelSize;
936 
937 			const vk::VkImageToMemoryCopyEXT region =
938 			{
939 				vk::VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT,	// VkStructureType				sType;
940 				DE_NULL,										// const void*					pNext;
941 				&paddedData[dataOffset],								// void*						memoryHostPointer;
942 				memoryRowLength,								// uint32_t						memoryRowLength;
943 				memoryImageHeight,								// uint32_t						memoryImageHeight;
944 				outputSubresourceLayers,						// VkImageSubresourceLayers		imageSubresource;
945 				offset,											// VkOffset3D					imageOffset;
946 				extent,											// VkExtent3D					imageExtent;
947 			};
948 
949 			regions[i] = region;
950 		}
951 
952 		const vk::VkCopyImageToMemoryInfoEXT copyImageToMemoryInfo =
953 		{
954 			vk::VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT,	// VkStructureType					sType;
955 			DE_NULL,												// const void*						pNext;
956 			0u,														// VkMemoryImageCopyFlagsEXT		flags;
957 			**outputImage,											// VkImage							srcImage;
958 			m_parameters.srcLayout,									// VkImageLayout					srcImageLayout;
959 			(deUint32)regions.size(),								// uint32_t							regionCount;
960 			regions.data(),											// const VkImageToMemoryCopyEXT*	pRegions;
961 		};
962 		vk.copyImageToMemoryEXT(device, &copyImageToMemoryInfo);
963 		commandsLog << "vkCopyImageToMemoryEXT() with image " << **outputImage << "\n";
964 
965 		for (deUint32 j = 0; j < mipImageSize.height; ++j)
966 		{
967 			for (deUint32 i = 0; i < mipImageSize.width; ++i)
968 			{
969 				for (deUint32 k = 0; k < outputNumChannels * outputChannelSize; ++k)
970 				{
971 					deUint32 dstIndex = j * mipImageSize.width * (outputNumChannels * outputChannelSize) + i * (outputNumChannels * outputChannelSize) + k;
972 					deUint32 srcIndex = j * (mipImageSize.width + m_parameters.padding) * (outputNumChannels * outputChannelSize) + i * (outputNumChannels * outputChannelSize) + k;
973 					data[dstIndex] = paddedData[srcIndex];
974 				}
975 			}
976 		}
977 
978 		bool match = memcmp(data.data(), resultBuffer.getDataPtr(), outputBufferSize) == 0;
979 		if (!match)
980 		{
981 			log << tcu::TestLog::Message << commandsLog.str() << tcu::TestLog::EndMessage;
982 			for (deUint32 i = 0; i < outputBufferSize; ++i) {
983 				if (data[i] != ((deUint8*)resultBuffer.getDataPtr())[i])
984 				{
985 					log << tcu::TestLog::Message << "At byte " << i << " data from vkCopyImageToMemoryEXT() is " << data[i] << ", but data from vkCmdCopyImageToBuffer() (after padding) is " << ((deUint8*)resultBuffer.getDataPtr())[i] << tcu::TestLog::EndMessage;
986 					break;
987 				}
988 			}
989 			return tcu::TestStatus::fail("copyImageToMemoryEXT failed");
990 		}
991 	}
992 
993 	if (m_parameters.imageOutputFormat == m_parameters.imageSampledFormat) {
994 		std::vector<deUint8> resultData(sampledBufferSize);
995 		const Allocation& outputAlloc = colorOutputBuffer->getAllocation();
996 		deMemcpy(resultData.data(), outputAlloc.getHostPtr(), sampledBufferSize);
997 
998 		for (uint32_t i = 0; i < sampledBufferSize; ++i) {
999 			if (resultData[i] != testData[i]) {
1000 
1001 				if (!isCompressedFormat(m_parameters.imageSampledFormat))
1002 				{
1003 					const tcu::ConstPixelBufferAccess bufferData(mapVkFormat(m_parameters.imageSampledFormat),
1004 						m_parameters.imageSize.width,
1005 						m_parameters.imageSize.height,
1006 						m_parameters.imageSize.depth,
1007 						outputAlloc.getHostPtr());
1008 
1009 					m_context.getTestContext().getLog()
1010 						<< tcu::TestLog::Section("host_copy_result", "host_copy_result")
1011 						<< tcu::LogImage("image", "", bufferData)
1012 						<< tcu::TestLog::EndSection;
1013 				}
1014 
1015 				return tcu::TestStatus::fail("Image verification failed");
1016 			}
1017 		}
1018 	}
1019 	return tcu::TestStatus::pass("Pass");
1020 }
1021 
1022 class HostImageCopyTestCase : public vkt::TestCase
1023 {
1024 public:
HostImageCopyTestCase(tcu::TestContext & context,const char * name,const TestParameters & parameters)1025 								HostImageCopyTestCase	(tcu::TestContext& context, const char* name, const TestParameters& parameters)
1026 								: TestCase		(context, name)
1027 								, m_parameters	(parameters)
1028 								{
1029 								}
1030 private:
1031 	void						checkSupport			(vkt::Context& context) const;
1032 	void						initPrograms			(vk::SourceCollections& programCollection) const;
createInstance(vkt::Context & context) const1033 	vkt::TestInstance*			createInstance			(vkt::Context& context) const { return new HostImageCopyTestInstance(context, m_parameters); }
1034 
1035 	const TestParameters	m_parameters;
1036 };
1037 
checkSupport(vkt::Context & context) const1038 void HostImageCopyTestCase::checkSupport (vkt::Context& context) const
1039 {
1040 	vk::VkInstance										instance		(context.getInstance());
1041 	vk::InstanceDriver									instanceDriver	(context.getPlatformInterface(), instance);
1042 	const vk::InstanceInterface&						vki				= context.getInstanceInterface();
1043 	vk::VkPhysicalDevice								physicalDevice	= context.getPhysicalDevice();
1044 
1045 	context.requireDeviceFunctionality("VK_EXT_host_image_copy");
1046 
1047 	if (m_parameters.dynamicRendering)
1048 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1049 
1050 	if (m_parameters.sparse)
1051 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SPARSE_BINDING);
1052 
1053 	vk::VkPhysicalDeviceHostImageCopyFeaturesEXT hostImageCopyFeatures =
1054 	{
1055 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT,				// VkStructureType					sType
1056 		DE_NULL,																		// const void*						pNext
1057 		VK_FALSE,																		// VkBool32							hostImageCopy;
1058 	};
1059 
1060 	vk::VkPhysicalDeviceFeatures				features;
1061 	deMemset(&features, 0, sizeof(vk::VkPhysicalDeviceFeatures));
1062 	vk::VkPhysicalDeviceFeatures2				features2 =
1063 	{
1064 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,			// VkStructureType					sType
1065 		&hostImageCopyFeatures,										// const void*						pNext
1066 		features													// VkPhysicalDeviceFeatures			features
1067 	};
1068 
1069 	instanceDriver.getPhysicalDeviceFeatures2(physicalDevice, &features2);
1070 
1071 	vk::VkPhysicalDeviceHostImageCopyPropertiesEXT hostImageCopyProperties =
1072 	{
1073 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT,	// VkStructureType	sType;
1074 		DE_NULL,																// void*			pNext;
1075 		0u,																		// uint32_t			copySrcLayoutCount;
1076 		DE_NULL,																// VkImageLayout*	pCopySrcLayouts;
1077 		0u,																		// uint32_t			copyDstLayoutCount;
1078 		DE_NULL,																// VkImageLayout*	pCopyDstLayouts;
1079 		{},																		// uint8_t			optimalTilingLayoutUUID[VK_UUID_SIZE];
1080 		DE_FALSE																// VkBool32			identicalMemoryTypeRequirements;
1081 	};
1082 	getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1083 	std::vector<vk::VkImageLayout> srcLayouts(hostImageCopyProperties.copySrcLayoutCount);
1084 	std::vector<vk::VkImageLayout> dstLayouts(hostImageCopyProperties.copyDstLayoutCount);
1085 	hostImageCopyProperties.pCopySrcLayouts = srcLayouts.data();
1086 	hostImageCopyProperties.pCopyDstLayouts = dstLayouts.data();
1087 	getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1088 	bool layoutSupported = false;
1089 	bool intermediateLayoutSupported = false;
1090 	for (deUint32 i = 0; i < hostImageCopyProperties.copySrcLayoutCount; ++i)
1091 	{
1092 		if (hostImageCopyProperties.pCopySrcLayouts[i] == m_parameters.srcLayout)
1093 			layoutSupported = true;
1094 		if (hostImageCopyProperties.pCopySrcLayouts[i] == m_parameters.intermediateLayout)
1095 			intermediateLayoutSupported = true;
1096 	}
1097 	if (layoutSupported == false || intermediateLayoutSupported == false)
1098 		TCU_THROW(NotSupportedError, "Layout not supported for src host copy");
1099 	layoutSupported = false;
1100 	for (deUint32 i = 0; i < hostImageCopyProperties.copyDstLayoutCount; ++i)
1101 	{
1102 		if (hostImageCopyProperties.pCopyDstLayouts[i] == m_parameters.dstLayout)
1103 		{
1104 			layoutSupported = true;
1105 			break;
1106 		}
1107 	}
1108 	if (layoutSupported == false)
1109 		TCU_THROW(NotSupportedError, "Layout not supported for dst host copy");
1110 
1111 	vk::VkImageUsageFlags	usage = vk::VK_IMAGE_USAGE_SAMPLED_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1112 	if (m_parameters.hostCopyMemoryToImage || m_parameters.hostCopyImageToMemory || m_parameters.memcpyFlag || m_parameters.hostTransferLayout)
1113 		usage |= vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
1114 	if (m_parameters.intermediateLayout == vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
1115 		usage |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1116 	else if (m_parameters.intermediateLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
1117 		usage |= vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1118 	else if (m_parameters.intermediateLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
1119 		usage |= vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1120 
1121 	vk::VkImageCreateFlags	flags = 0u;
1122 	if (m_parameters.sparse)
1123 		flags |= vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT | vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT;
1124 	vk::VkImageFormatProperties imageFormatProperties;
1125 	if (vki.getPhysicalDeviceImageFormatProperties(physicalDevice, m_parameters.imageSampledFormat, vk::VK_IMAGE_TYPE_2D,
1126 		m_parameters.sampledTiling, usage, flags,
1127 		&imageFormatProperties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
1128 		TCU_THROW(NotSupportedError, "Image format not supported.");
1129 
1130 	vk::VkImageUsageFlags outputUsage = vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1131 	if (m_parameters.outputImageHostTransition || m_parameters.hostCopyImageToMemory)
1132 		outputUsage |= vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
1133 	if (m_parameters.command == DISPATCH)
1134 		outputUsage |= vk::VK_IMAGE_USAGE_STORAGE_BIT;
1135 	vk::VkImageFormatProperties outputImageFormatProperties;
1136 	if (vki.getPhysicalDeviceImageFormatProperties(physicalDevice, m_parameters.imageOutputFormat, vk::VK_IMAGE_TYPE_2D,
1137 		vk::VK_IMAGE_TILING_OPTIMAL, outputUsage, flags,
1138 		&outputImageFormatProperties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
1139 		TCU_THROW(NotSupportedError, "Image format not supported.");
1140 
1141 	vk::VkFormatProperties3 formatProperties3 = vk::initVulkanStructure();
1142 	vk::VkFormatProperties2 formatProperties2 = vk::initVulkanStructure(&formatProperties3);
1143 	vki.getPhysicalDeviceFormatProperties2(context.getPhysicalDevice(), m_parameters.imageSampledFormat, &formatProperties2);
1144 	if (m_parameters.sampledTiling == vk::VK_IMAGE_TILING_LINEAR && (formatProperties3.linearTilingFeatures & vk::VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0)
1145 		TCU_THROW(NotSupportedError, "Format feature host image transfer not supported for linear tiling.");
1146 	if (m_parameters.sampledTiling == vk::VK_IMAGE_TILING_OPTIMAL && (formatProperties3.optimalTilingFeatures & vk::VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0)
1147 		TCU_THROW(NotSupportedError, "Format feature host image transfer not supported for optimal tiling.");
1148 
1149 	if (hostImageCopyFeatures.hostImageCopy != VK_TRUE)
1150 		TCU_THROW(NotSupportedError, "hostImageCopy not supported");
1151 	if (imageFormatProperties.maxMipLevels <= m_parameters.mipLevel)
1152 		TCU_THROW(NotSupportedError, "Required image mip levels not supported.");
1153 
1154 	if (m_parameters.command == DISPATCH)
1155 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT);
1156 }
1157 
initPrograms(vk::SourceCollections & programCollection) const1158 void HostImageCopyTestCase::initPrograms (vk::SourceCollections& programCollection) const
1159 {
1160 	{
1161 		std::ostringstream vert;
1162 		vert
1163 			<< "#version 450\n"
1164 			<< "layout (location=0) out vec2 texCoord;\n"
1165 			<< "void main()\n"
1166 			<< "{\n"
1167 			<< "	texCoord = vec2(gl_VertexIndex & 1u, (gl_VertexIndex >> 1u) & 1u);"
1168 			<< "    gl_Position = vec4(texCoord * 2.0f - 1.0f, 0.0f, 1.0f);\n"
1169 			<< "}\n"
1170 			;
1171 
1172 		programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
1173 	}
1174 	{
1175 		std::string output;
1176 		if (isDepthStencilFormat(m_parameters.imageSampledFormat))
1177 			output = "    out_color = vec4(texture(combinedSampler, texCoord).r, 0, 0, 0);\n";
1178 		else
1179 			output = "    out_color = texture(combinedSampler, texCoord);\n";
1180 
1181 		std::ostringstream frag;
1182 		frag
1183 			<< "#version 450\n"
1184 			<< "layout (location=0) out vec4 out_color;\n"
1185 			<< "layout (location=0) in vec2 texCoord;\n"
1186 			<< "layout (set=0, binding=0) uniform sampler2D combinedSampler;\n"
1187 			<< "void main()\n"
1188 			<< "{\n"
1189 			<< output
1190 			<< "}\n"
1191 			;
1192 
1193 		programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1194 	}
1195 	{
1196 		std::string image;
1197 		std::string output;
1198 		if (m_parameters.imageOutputFormat == vk::VK_FORMAT_R8G8B8A8_UINT)
1199 		{
1200 			image	= "uimage2D";
1201 			output	= "uvec4(texture(combinedSampler, vec2(pixelCoord) / (textureSize(combinedSampler, 0) - vec2(0.001f))) * 255)";
1202 		}
1203 		else
1204 		{
1205 			image = "image2D";
1206 			output = "texture(combinedSampler, vec2(pixelCoord) / (textureSize(combinedSampler, 0) - vec2(0.001f)))";
1207 		}
1208 
1209 		std::ostringstream comp;
1210 		comp
1211 			<< "#version 450\n"
1212 			<< "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1213 			<< "layout (set=0, binding=0) uniform sampler2D combinedSampler;\n"
1214 			<< "layout (set=0, binding=1) uniform writeonly " << image << " outImage;\n"
1215 			<< "void main()\n"
1216 			<< "{\n"
1217 			<< "	ivec2 pixelCoord = ivec2(gl_GlobalInvocationID.xy);\n"
1218 			<< "	imageStore(outImage, pixelCoord, " << output << ");\n"
1219 			<< "}\n"
1220 			;
1221 
1222 		programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
1223 	}
1224 }
1225 
1226 class PreinitializedTestInstance : public vkt::TestInstance
1227 {
1228 public:
PreinitializedTestInstance(vkt::Context & context,const vk::VkFormat format,vk::VkImageLayout srcLayout,vk::VkImageLayout dstLayout,vk::VkExtent3D size,deUint32 arrayLayers,bool imageToImageCopy,bool memcpy,vk::VkImageTiling tiling)1229 	PreinitializedTestInstance	(vkt::Context& context, const vk::VkFormat format, vk::VkImageLayout srcLayout, vk::VkImageLayout dstLayout, vk::VkExtent3D size, deUint32 arrayLayers, bool imageToImageCopy, bool memcpy, vk::VkImageTiling tiling)
1230 								: vkt::TestInstance		(context)
1231 								, m_format				(format)
1232 								, m_srcLayout			(srcLayout)
1233 								, m_dstLayout			(dstLayout)
1234 								, m_size				(size)
1235 								, m_arrayLayers			(arrayLayers)
1236 								, m_imageToImageCopy	(imageToImageCopy)
1237 								, m_memcpy				(memcpy)
1238 								, m_tiling				(tiling)
1239 								{
1240 								}
1241 
1242 private:
1243 	tcu::TestStatus				iterate			(void);
1244 
1245 	const vk::VkFormat			m_format;
1246 	const vk::VkImageLayout		m_srcLayout;
1247 	const vk::VkImageLayout		m_dstLayout;
1248 	const vk::VkExtent3D		m_size;
1249 	const deUint32				m_arrayLayers;
1250 	const bool					m_imageToImageCopy;
1251 	const bool					m_memcpy;
1252 	const vk::VkImageTiling		m_tiling;
1253 };
1254 
iterate(void)1255 tcu::TestStatus PreinitializedTestInstance::iterate (void)
1256 {
1257 	vk::InstanceDriver				instanceDriver		(m_context.getPlatformInterface(), m_context.getInstance());
1258 	vk::VkPhysicalDevice			physicalDevice		= m_context.getPhysicalDevice();
1259 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
1260 	const vk::VkDevice				device				= m_context.getDevice();
1261 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1262 	const vk::VkQueue				queue				= m_context.getUniversalQueue();
1263 	auto&							alloc				= m_context.getDefaultAllocator();
1264 	tcu::TestLog&					log					= m_context.getTestContext().getLog();
1265 
1266 	const auto						subresourceRange	= makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_arrayLayers);
1267 	const auto						subresourceLayers	= makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, m_arrayLayers);
1268 	const vk::VkOffset3D			offset				= { 0u, 0u, 0u };
1269 
1270 	const auto						channelSize			= getChannelSize(m_format);
1271 	const auto						numChannels			= getNumChannels(m_format);
1272 	const auto						bufferCount			= m_size.width * m_size.height * m_size.depth * m_arrayLayers * numChannels;
1273 	const auto						bufferSize			= bufferCount * channelSize;
1274 
1275 	const vk::VkCommandPoolCreateInfo	cmdPoolInfo =
1276 	{
1277 		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// sType
1278 		DE_NULL,												// pNext
1279 		vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// flags
1280 		queueFamilyIndex,										// queuefamilyindex
1281 	};
1282 	const Move	<vk::VkCommandPool>		cmdPool				(createCommandPool(vk, device, &cmdPoolInfo));
1283 	const Move	<vk::VkCommandBuffer>	cmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1284 
1285 	const vk::VkImageType				imageType			= m_size.depth > 1 ? vk::VK_IMAGE_TYPE_3D : vk::VK_IMAGE_TYPE_2D;
1286 
1287 	deUint64										modifier = 0;
1288 	checkSupportedFormatFeatures(instanceDriver, physicalDevice, m_format, m_tiling, &modifier);
1289 
1290 	vk::VkImageDrmFormatModifierListCreateInfoEXT	drmCreateInfo	= vk::initVulkanStructure();
1291 	drmCreateInfo.drmFormatModifierCount					= 1;
1292 	drmCreateInfo.pDrmFormatModifiers						= &modifier;
1293 
1294 	vk::VkImageCreateInfo				createInfo			=
1295 	{
1296 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
1297 		m_tiling == vk::VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT ? &drmCreateInfo : DE_NULL,
1298 													// const void*				pNext
1299 		0u,											// VkImageCreateFlags		flags
1300 		imageType,									// VkImageType				imageType
1301 		m_format,									// VkFormat					format
1302 		m_size,										// VkExtent3D				extent
1303 		1u,											// uint32_t					mipLevels
1304 		m_arrayLayers,								// uint32_t					arrayLayers
1305 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
1306 		m_tiling,									// VkImageTiling			tiling
1307 		vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
1308 													// VkImageUsageFlags		usage
1309 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
1310 		0,											// uint32_t					queueFamilyIndexCount
1311 		DE_NULL,									// const uint32_t*			pQueueFamilyIndices
1312 		vk::VK_IMAGE_LAYOUT_PREINITIALIZED			// VkImageLayout			initialLayout
1313 	};
1314 
1315 	de::MovePtr<ImageWithMemory>	image				= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::HostVisible));
1316 	de::MovePtr<ImageWithMemory>	copyImage			= de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
1317 	const vk::VkImage				endImage			= m_imageToImageCopy ? **copyImage : **image;
1318 	de::MovePtr<BufferWithMemory>	outputBuffer		= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, alloc, makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
1319 
1320 	vk::Allocation&					allocation			= image->getAllocation();
1321 	void*							ptr					= allocation.getHostPtr();
1322 	generateData(ptr, bufferSize, m_format);
1323 
1324 	vk::VkPhysicalDeviceHostImageCopyPropertiesEXT hostImageCopyProperties =
1325 	{
1326 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT,	// VkStructureType	sType;
1327 		DE_NULL,																// void*			pNext;
1328 		0u,																		// uint32_t			copySrcLayoutCount;
1329 		DE_NULL,																// VkImageLayout*	pCopySrcLayouts;
1330 		0u,																		// uint32_t			copyDstLayoutCount;
1331 		DE_NULL,																// VkImageLayout*	pCopyDstLayouts;
1332 		{},																		// uint8_t			optimalTilingLayoutUUID[VK_UUID_SIZE];
1333 		DE_FALSE,																// VkBool32			identicalMemoryTypeRequirements;
1334 	};
1335 	getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1336 	if (hostImageCopyProperties.identicalMemoryTypeRequirements)
1337 	{
1338 		createInfo.flags &= ~(vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT);
1339 		de::MovePtr<ImageWithMemory>	imageWithoutHostCopy = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::HostVisible));
1340 		vk::VkMemoryRequirements hostImageMemoryRequirements;
1341 		vk::VkMemoryRequirements memoryRequirements;
1342 		vk.getImageMemoryRequirements(device, **image, &hostImageMemoryRequirements);
1343 		vk.getImageMemoryRequirements(device, **imageWithoutHostCopy, &memoryRequirements);
1344 
1345 		if (hostImageMemoryRequirements.memoryTypeBits != memoryRequirements.memoryTypeBits)
1346 			TCU_THROW(NotSupportedError, "Layout not supported for src host copy");
1347 	}
1348 
1349 	// map device memory and initialize
1350 	{
1351 		const vk::VkHostImageLayoutTransitionInfoEXT transition =
1352 		{
1353 			vk::VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,		// VkStructureType			sType;
1354 			DE_NULL,															// const void*				pNext;
1355 			image->get(),														// VkImage					image;
1356 			vk::VK_IMAGE_LAYOUT_PREINITIALIZED,									// VkImageLayout			oldLayout;
1357 			m_srcLayout,														// VkImageLayout			newLayout;
1358 			subresourceRange													// VkImageSubresourceRange	subresourceRange;
1359 		};
1360 		vk.transitionImageLayoutEXT(device, 1, &transition);
1361 	}
1362 
1363 	if (m_imageToImageCopy)
1364 	{
1365 		vk::VkHostImageLayoutTransitionInfoEXT transition =
1366 		{
1367 			vk::VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,		// VkStructureType			sType;
1368 			DE_NULL,															// const void*				pNext;
1369 			copyImage->get(),													// VkImage					image;
1370 			vk::VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout			oldLayout;
1371 			m_dstLayout,														// VkImageLayout			newLayout;
1372 			subresourceRange													// VkImageSubresourceRange	subresourceRange;
1373 		};
1374 		vk.transitionImageLayoutEXT(device, 1, &transition);
1375 
1376 		const vk::VkImageCopy2KHR	region =
1377 		{
1378 			vk::VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR,		// VkStructureType				sType;
1379 			DE_NULL,									// const void*					pNext;
1380 			subresourceLayers,							// VkImageSubresourceLayers		srcSubresource;
1381 			offset,										// VkOffset3D					srcOffset;
1382 			subresourceLayers,							// VkImageSubresourceLayers		dstSubresource;
1383 			offset,										// VkOffset3D					dstOffset;
1384 			m_size										// VkExtent3D					extent;
1385 		};
1386 
1387 		const vk::VkHostImageCopyFlagsEXT	hostImageCopyFlags		= m_memcpy ? (vk::VkHostImageCopyFlagsEXT)vk::VK_HOST_IMAGE_COPY_MEMCPY_EXT : (vk::VkHostImageCopyFlagsEXT)0u;
1388 
1389 		const vk::VkCopyImageToImageInfoEXT copyImageToImageInfo	=
1390 		{
1391 			vk::VK_STRUCTURE_TYPE_COPY_IMAGE_TO_IMAGE_INFO_EXT,			// VkStructureType			sType;
1392 			DE_NULL,													// const void*				pNext;
1393 			hostImageCopyFlags,											// VkHostImageCopyFlagsEXT	flags;
1394 			**image,													// VkImage					srcImage;
1395 			m_srcLayout,												// VkImageLayout			srcImageLayout;
1396 			**copyImage,												// VkImage					dstImage;
1397 			m_dstLayout,												// VkImageLayout			dstImageLayout;
1398 			1u,															// uint32_t					regionCount;
1399 			&region,													// const VkImageCopy2*		pRegions;
1400 		};
1401 
1402 		vk.copyImageToImageEXT(device, &copyImageToImageInfo);
1403 
1404 		transition.oldLayout = m_dstLayout;
1405 		transition.newLayout = m_srcLayout;
1406 		vk.transitionImageLayoutEXT(device, 1, &transition);
1407 	}
1408 
1409 	deUint8* data = new deUint8[bufferSize];
1410 
1411 	const vk::VkImageToMemoryCopyEXT region =
1412 	{
1413 		vk::VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT,	// VkStructureType				sType;
1414 		DE_NULL,										// const void*					pNext;
1415 		data,											// void*						memoryHostPointer;
1416 		0u,												// uint32_t						memoryRowLength;
1417 		0u,												// uint32_t						memoryImageHeight;
1418 		subresourceLayers,								// VkImageSubresourceLayers		imageSubresource;
1419 		offset,											// VkOffset3D					imageOffset;
1420 		m_size,											// VkExtent3D					imageExtent;
1421 	};
1422 
1423 	const vk::VkCopyImageToMemoryInfoEXT copyImageToMemoryInfo =
1424 	{
1425 		vk::VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT,	// VkStructureType					sType;
1426 		DE_NULL,												// const void*						pNext;
1427 		0u,														// VkMemoryImageCopyFlagsEXT		flags;
1428 		endImage,												// VkImage							srcImage;
1429 		m_srcLayout,											// VkImageLayout					srcImageLayout;
1430 		1,														// uint32_t							regionCount;
1431 		&region,												// const VkImageToMemoryCopyEXT*	pRegions;
1432 	};
1433 	vk.copyImageToMemoryEXT(device, &copyImageToMemoryInfo);
1434 
1435 	vk::beginCommandBuffer(vk, *cmdBuffer);
1436 	{
1437 		const vk::VkHostImageLayoutTransitionInfoEXT transition =
1438 		{
1439 			vk::VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,		// VkStructureType			sType;
1440 			DE_NULL,															// const void*				pNext;
1441 			**image,															// VkImage					image;
1442 			m_srcLayout,														// VkImageLayout			oldLayout;
1443 			vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,							// VkImageLayout			newLayout;
1444 			subresourceRange													// VkImageSubresourceRange subresourceRange;
1445 		};
1446 		vk.transitionImageLayoutEXT(device, 1, &transition);
1447 
1448 		const vk::VkBufferImageCopy	copyRegion	=
1449 		{
1450 			0u,												// VkDeviceSize				bufferOffset;
1451 			0u,												// deUint32					bufferRowLength;
1452 			0u,												// deUint32					bufferImageHeight;
1453 			subresourceLayers,								// VkImageSubresourceLayers	imageSubresource;
1454 			offset,											// VkOffset3D				imageOffset;
1455 			m_size											// VkExtent3D				imageExtent;
1456 		};
1457 		vk.cmdCopyImageToBuffer(*cmdBuffer, **image, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **outputBuffer, 1u, &copyRegion);
1458 	}
1459 	vk::endCommandBuffer(vk, *cmdBuffer);
1460 
1461 	vk::submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1462 	auto outputPtr = outputBuffer->getAllocation().getHostPtr();
1463 	bool match = memcmp(data, outputPtr, bufferSize) == 0;
1464 
1465 	if (!match)
1466 	{
1467 		for (deUint32 i = 0; i < bufferSize; ++i) {
1468 			if (data[i] != ((deUint8*)outputPtr)[i])
1469 			{
1470 				log << tcu::TestLog::Message << "At byte " << i << " data from vkCopyImageToMemoryEXT() is " << data[i] << ", but data from vkCmdCopyImageToBuffer() is " << ((deUint8*)outputPtr)[i] << tcu::TestLog::EndMessage;
1471 				break;
1472 			}
1473 		}
1474 	}
1475 
1476 	delete[] data;
1477 
1478 	if (!match)
1479 	{
1480 		return tcu::TestStatus::fail("Copies values do not match");
1481 	}
1482 
1483 	return tcu::TestStatus::pass("Pass");
1484 }
1485 
1486 class PreinitializedTestCase : public vkt::TestCase
1487 {
1488 public:
PreinitializedTestCase(tcu::TestContext & context,const char * name,const vk::VkFormat format,vk::VkImageLayout srcLayout,vk::VkImageLayout dstLayout,vk::VkExtent3D size,deUint32 arrayLayers,bool imageToImageCopy,bool memcpy,vk::VkImageTiling tiling)1489 	PreinitializedTestCase						(tcu::TestContext& context, const char* name, const vk::VkFormat format, vk::VkImageLayout srcLayout, vk::VkImageLayout dstLayout, vk::VkExtent3D size, deUint32 arrayLayers, bool imageToImageCopy, bool memcpy, vk::VkImageTiling tiling)
1490 												: TestCase				(context, name)
1491 												, m_format				(format)
1492 												, m_srcLayout			(srcLayout)
1493 												, m_dstLayout			(dstLayout)
1494 												, m_size				(size)
1495 												, m_arrayLayers			(arrayLayers)
1496 												, m_imageToImageCopy	(imageToImageCopy)
1497 												, m_memcpy				(memcpy)
1498 												, m_tiling				(tiling)
1499 												{
1500 												}
1501 private:
1502 	void						checkSupport	(vkt::Context& context) const;
createInstance(vkt::Context & context) const1503 	vkt::TestInstance*			createInstance	(vkt::Context& context) const { return new PreinitializedTestInstance(context, m_format, m_srcLayout, m_dstLayout, m_size, m_arrayLayers, m_imageToImageCopy, m_memcpy, m_tiling); }
1504 
1505 	const vk::VkFormat			m_format;
1506 	const vk::VkImageLayout		m_srcLayout;
1507 	const vk::VkImageLayout		m_dstLayout;
1508 	const vk::VkExtent3D		m_size;
1509 	const deUint32				m_arrayLayers;
1510 	const bool					m_imageToImageCopy;
1511 	const bool					m_memcpy;
1512 	const vk::VkImageTiling		m_tiling;
1513 };
1514 
checkSupport(vkt::Context & context) const1515 void PreinitializedTestCase::checkSupport (vkt::Context& context) const
1516 {
1517 	vk::VkInstance							instance		(context.getInstance());
1518 	vk::InstanceDriver						instanceDriver	(context.getPlatformInterface(), instance);
1519 	const InstanceInterface&				vki				= context.getInstanceInterface();
1520 	vk::VkPhysicalDevice					physicalDevice	= context.getPhysicalDevice();
1521 
1522 	context.requireDeviceFunctionality("VK_EXT_host_image_copy");
1523 
1524 	if (m_tiling == vk::VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
1525 		context.requireDeviceFunctionality("VK_EXT_image_drm_format_modifier");
1526 
1527 	if (m_srcLayout == vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR || m_dstLayout == vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
1528 		context.requireDeviceFunctionality("VK_KHR_swapchain");
1529 
1530 	if (m_srcLayout == vk::VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL || m_dstLayout == vk::VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL ||
1531 		m_srcLayout == vk::VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR || m_dstLayout == vk::VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR)
1532 		context.requireDeviceFunctionality("VK_KHR_maintenance2");
1533 
1534 	if (m_srcLayout == vk::VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL || m_dstLayout == vk::VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
1535 		m_srcLayout == vk::VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL || m_dstLayout == vk::VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL ||
1536 		m_srcLayout == vk::VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL || m_dstLayout == vk::VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL)
1537 		context.requireDeviceFunctionality("VK_KHR_separate_depth_stencil_layouts");
1538 
1539 	if (m_srcLayout == vk::VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL || m_dstLayout == vk::VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL ||
1540 		m_srcLayout == vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL || m_dstLayout == vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL)
1541 		context.requireDeviceFunctionality("VK_KHR_synchronization2");
1542 
1543 	if (m_srcLayout == vk::VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT || m_dstLayout == vk::VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT)
1544 		context.requireDeviceFunctionality("VK_EXT_attachment_feedback_loop_layout");
1545 
1546 	vk::VkPhysicalDeviceHostImageCopyFeaturesEXT hostImageCopyFeatures =
1547 	{
1548 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT,				// VkStructureType					sType
1549 		DE_NULL,																		// const void*						pNext
1550 		VK_FALSE,																		// VkBool32							hostImageCopy;
1551 	};
1552 
1553 	vk::VkPhysicalDeviceFeatures				features;
1554 	deMemset(&features, 0, sizeof(vk::VkPhysicalDeviceFeatures));
1555 	vk::VkPhysicalDeviceFeatures2				features2 =
1556 	{
1557 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,			// VkStructureType					sType
1558 		&hostImageCopyFeatures,										// const void*						pNext
1559 		features													// VkPhysicalDeviceFeatures			features
1560 	};
1561 
1562 	instanceDriver.getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
1563 
1564 	vk::VkPhysicalDeviceHostImageCopyPropertiesEXT hostImageCopyProperties =
1565 	{
1566 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT,	// VkStructureType	sType;
1567 		DE_NULL,																// void*			pNext;
1568 		0u,																		// uint32_t			copySrcLayoutCount;
1569 		DE_NULL,																// VkImageLayout*	pCopySrcLayouts;
1570 		0u,																		// uint32_t			copyDstLayoutCount;
1571 		DE_NULL,																// VkImageLayout*	pCopyDstLayouts;
1572 		{},																		// uint8_t			optimalTilingLayoutUUID[VK_UUID_SIZE];
1573 		DE_FALSE																// VkBool32			identicalMemoryTypeRequirements;
1574 	};
1575 
1576 	getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1577 	std::vector<vk::VkImageLayout> srcLayouts(hostImageCopyProperties.copySrcLayoutCount);
1578 	std::vector<vk::VkImageLayout> dstLayouts(hostImageCopyProperties.copyDstLayoutCount);
1579 	hostImageCopyProperties.pCopySrcLayouts = srcLayouts.data();
1580 	hostImageCopyProperties.pCopyDstLayouts = dstLayouts.data();
1581 	getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1582 
1583 	bool layoutSupported = false;
1584 	for (deUint32 i = 0; i < hostImageCopyProperties.copySrcLayoutCount; ++i)
1585 	{
1586 		if (hostImageCopyProperties.pCopySrcLayouts[i] == m_srcLayout)
1587 			layoutSupported = true;
1588 	}
1589 	if (layoutSupported == false)
1590 		TCU_THROW(NotSupportedError, "Layout not supported for src host copy");
1591 	layoutSupported = false;
1592 	for (deUint32 i = 0; i < hostImageCopyProperties.copyDstLayoutCount; ++i)
1593 	{
1594 		if (hostImageCopyProperties.pCopyDstLayouts[i] == m_dstLayout)
1595 			layoutSupported = true;
1596 	}
1597 	if (layoutSupported == false)
1598 		TCU_THROW(NotSupportedError, "Layout not supported for dst host copy");
1599 
1600 	if (hostImageCopyFeatures.hostImageCopy != VK_TRUE)
1601 		TCU_THROW(NotSupportedError, "hostImageCopy not supported");
1602 
1603 	deUint64 modifier = 0;
1604 	checkSupportedFormatFeatures(instanceDriver, physicalDevice, m_format, m_tiling, &modifier);
1605 
1606 	vk::VkImageType const imageType = m_size.depth > 1 ? vk::VK_IMAGE_TYPE_3D : vk::VK_IMAGE_TYPE_2D;
1607 	vk::VkImageFormatProperties2 imageFormatProperties =
1608 	{
1609 		vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,	// VkStructureType			sType;
1610 		DE_NULL,											// void* pNext;
1611 		{},													// VkImageFormatProperties	imageFormatProperties;
1612 	};
1613 	vk::VkPhysicalDeviceImageDrmFormatModifierInfoEXT modifierInfo = {
1614 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,			// VkStructureType	sType;
1615 		DE_NULL,																			// const void*		pNext;
1616 		modifier,																			// uint64_t			drmFormatModifier;
1617 		VK_SHARING_MODE_EXCLUSIVE,															// VkSharingMode	sharingMode;
1618 		0u,																					// uint32_t			queueFamilyIndexCount;
1619 		DE_NULL																				// const uint32_t*	pQueueFamilyIndices;
1620 	};
1621 	vk::VkPhysicalDeviceImageFormatInfo2 imageFormatInfo =
1622 	{
1623 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,							// VkStructureType		sType;
1624 		m_tiling == vk::VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT ? &modifierInfo : DE_NULL,	// const void*			pNext;
1625 		m_format,																			// VkFormat				format;
1626 		imageType,																			// VkImageType			type;
1627 		m_tiling,																			// VkImageTiling		tiling;
1628 		vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags	usage;
1629 		(vk::VkImageCreateFlags)0u															// VkImageCreateFlags	flags;
1630 	};
1631 	if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &imageFormatInfo, &imageFormatProperties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
1632 		TCU_THROW(NotSupportedError, "Image format not supported.");
1633 	if (imageFormatProperties.imageFormatProperties.maxArrayLayers < m_arrayLayers)
1634 		TCU_THROW(NotSupportedError, "Required image array layers not supported.");
1635 }
1636 
1637 class PropertiesTestInstance : public vkt::TestInstance
1638 {
1639 public:
PropertiesTestInstance(vkt::Context & context)1640 	PropertiesTestInstance (vkt::Context& context)
1641 		: vkt::TestInstance (context)
1642 	{
1643 	}
1644 
1645 private:
1646 	tcu::TestStatus				iterate			(void);
1647 };
1648 
iterate(void)1649 tcu::TestStatus PropertiesTestInstance::iterate (void) {
1650 	vk::VkInstance										instance		(m_context.getInstance());
1651 	vk::InstanceDriver									instanceDriver	(m_context.getPlatformInterface(), instance);
1652 	vk::VkPhysicalDevice								physicalDevice	= m_context.getPhysicalDevice();
1653 
1654 	vk::VkPhysicalDeviceHostImageCopyPropertiesEXT hostImageCopyProperties =
1655 	{
1656 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT,	// VkStructureType	sType;
1657 		DE_NULL,																// void*			pNext;
1658 		0u,																		// uint32_t			copySrcLayoutCount;
1659 		DE_NULL,																// VkImageLayout*	pCopySrcLayouts;
1660 		0u,																		// uint32_t			copyDstLayoutCount;
1661 		DE_NULL,																// VkImageLayout*	pCopyDstLayouts;
1662 		{},																		// uint8_t			optimalTilingLayoutUUID[VK_UUID_SIZE];
1663 		DE_FALSE																// VkBool32			identicalMemoryTypeRequirements;
1664 	};
1665 	getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1666 	std::vector<vk::VkImageLayout> srcLayouts(hostImageCopyProperties.copySrcLayoutCount);
1667 	std::vector<vk::VkImageLayout> dstLayouts(hostImageCopyProperties.copyDstLayoutCount);
1668 	hostImageCopyProperties.pCopySrcLayouts = srcLayouts.data();
1669 	hostImageCopyProperties.pCopyDstLayouts = dstLayouts.data();
1670 	getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1671 
1672 	if (hostImageCopyProperties.copySrcLayoutCount == 0)
1673 		return tcu::TestStatus::fail("copySrcLayoutCount is 0");
1674 	if (hostImageCopyProperties.copyDstLayoutCount == 0)
1675 		return tcu::TestStatus::fail("copyDstLayoutCount is 0");
1676 
1677 	bool layoutSupported = false;
1678 	for (deUint32 i = 0; i < hostImageCopyProperties.copySrcLayoutCount; ++i)
1679 	{
1680 		if (hostImageCopyProperties.pCopySrcLayouts[i] == vk::VK_IMAGE_LAYOUT_GENERAL)
1681 			layoutSupported = true;
1682 	}
1683 	if (layoutSupported == false)
1684 		return tcu::TestStatus::fail("VK_IMAGE_LAYOUT_GENERAL not supported for src host copy");
1685 	layoutSupported = false;
1686 	for (deUint32 i = 0; i < hostImageCopyProperties.copyDstLayoutCount; ++i)
1687 	{
1688 		if (hostImageCopyProperties.pCopyDstLayouts[i] == vk::VK_IMAGE_LAYOUT_GENERAL)
1689 			layoutSupported = true;
1690 	}
1691 	if (layoutSupported == false)
1692 		return tcu::TestStatus::fail("VK_IMAGE_LAYOUT_GENERAL not supported for dst host copy");
1693 
1694 	return tcu::TestStatus::pass("Pass");
1695 }
1696 
1697 class PropertiesTestCase : public vkt::TestCase
1698 {
1699 public:
PropertiesTestCase(tcu::TestContext & context,const char * name)1700 	PropertiesTestCase (tcu::TestContext& context, const char* name)
1701 		: TestCase (context, name)
1702 	{
1703 	}
1704 private:
createInstance(vkt::Context & context) const1705 	vkt::TestInstance*			createInstance	(vkt::Context& context) const { return new PropertiesTestInstance(context); }
1706 	void						checkSupport	(vkt::Context& context) const;
1707 };
1708 
checkSupport(vkt::Context & context) const1709 void PropertiesTestCase::checkSupport (vkt::Context& context) const {
1710 	context.requireDeviceFunctionality("VK_EXT_host_image_copy");
1711 }
1712 
1713 class QueryTestInstance : public vkt::TestInstance
1714 {
1715 public:
QueryTestInstance(vkt::Context & context,const vk::VkFormat format,const vk::VkImageTiling tiling)1716 	QueryTestInstance (vkt::Context& context, const vk::VkFormat format, const vk::VkImageTiling tiling)
1717 		: vkt::TestInstance (context)
1718 		, m_format			(format)
1719 		, m_tiling			(tiling)
1720 	{
1721 	}
1722 
1723 private:
1724 	tcu::TestStatus				iterate			(void);
1725 
1726 	const vk::VkFormat			m_format;
1727 	const vk::VkImageTiling		m_tiling;
1728 };
1729 
iterate(void)1730 tcu::TestStatus QueryTestInstance::iterate (void)
1731 {
1732 	const InstanceInterface&			vki					= m_context.getInstanceInterface();
1733 	const vk::VkPhysicalDevice			physicalDevice		= m_context.getPhysicalDevice();
1734 	tcu::TestLog&						log					= m_context.getTestContext().getLog();
1735 
1736 	const vk::VkPhysicalDeviceImageFormatInfo2			imageFormatInfo =
1737 	{
1738 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,	// VkStructureType		sType;
1739 		DE_NULL,													// const void*			pNext;
1740 		m_format,													// VkFormat				format;
1741 		vk::VK_IMAGE_TYPE_2D,										// VkImageType			type;
1742 		m_tiling,													// VkImageTiling		tiling;
1743 		vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT,					// VkImageUsageFlags	usage;
1744 		(VkImageCreateFlags)0u										// VkImageCreateFlags	flags;
1745 	};
1746 
1747 	vk::VkHostImageCopyDevicePerformanceQueryEXT		hostImageCopyDevicePerformanceQuery = vk::initVulkanStructure();
1748 	vk::VkImageFormatProperties2						imageFormatProperties				= vk::initVulkanStructure(&hostImageCopyDevicePerformanceQuery);
1749 	vk::VkResult res = vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &imageFormatInfo, &imageFormatProperties);
1750 
1751 	if (hostImageCopyDevicePerformanceQuery.identicalMemoryLayout == VK_FALSE) {
1752 		if (hostImageCopyDevicePerformanceQuery.optimalDeviceAccess != VK_FALSE)
1753 		{
1754 			log << tcu::TestLog::Message << "VkHostImageCopyDevicePerformanceQueryEXT::identicalMemoryLayout is VK_FALSE, but VkHostImageCopyDevicePerformanceQueryEXT::optimalDeviceAccess is VK_TRUE" << tcu::TestLog::EndMessage;
1755 			return tcu::TestStatus::fail("Fail");
1756 		}
1757 	}
1758 	else
1759 	{
1760 		if (hostImageCopyDevicePerformanceQuery.optimalDeviceAccess != VK_TRUE)
1761 		{
1762 			log << tcu::TestLog::Message << "VkHostImageCopyDevicePerformanceQueryEXT::identicalMemoryLayout is VK_TRUE, but VkHostImageCopyDevicePerformanceQueryEXT::optimalDeviceAccess is VK_FALSE" << tcu::TestLog::EndMessage;
1763 			return tcu::TestStatus::fail("Fail");
1764 		}
1765 	}
1766 
1767 	if (isBlockCompressedFormat(m_format) && res == vk::VK_SUCCESS)
1768 	{
1769 		if (hostImageCopyDevicePerformanceQuery.optimalDeviceAccess != VK_TRUE)
1770 		{
1771 			log << tcu::TestLog::Message << "Format is a block compressed format and vkGetPhysicalDeviceImageFormatProperties2 returned VK_SUCCESS, but VkHostImageCopyDevicePerformanceQueryEXT::optimalDeviceAccess is VK_FALSE" << tcu::TestLog::EndMessage;
1772 			return tcu::TestStatus::fail("Fail");
1773 		}
1774 	}
1775 
1776 	if (!vk::isDepthStencilFormat(m_format))
1777 	{
1778 		vk::VkFormatProperties3	formatProperties3 = vk::initVulkanStructure();
1779 		vk::VkFormatProperties2 formatProperties2 = vk::initVulkanStructure(&formatProperties3);
1780 		vki.getPhysicalDeviceFormatProperties2(physicalDevice, m_format, &formatProperties2);
1781 
1782 		if (m_tiling == VK_IMAGE_TILING_OPTIMAL)
1783 		{
1784 			if ((formatProperties3.optimalTilingFeatures & VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0)
1785 			{
1786 				log << tcu::TestLog::Message << "VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT is supported in optimalTilingFeatures for format " << vk::getFormatStr(m_format).toString() << ", but VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT is not" << tcu::TestLog::EndMessage;
1787 				return tcu::TestStatus::fail("VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT not supported");
1788 			}
1789 		}
1790 		else if (m_tiling == VK_IMAGE_TILING_LINEAR)
1791 		{
1792 			if ((formatProperties3.linearTilingFeatures & VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0)
1793 			{
1794 				log << tcu::TestLog::Message << "VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT is supported in linearTilingFeatures for format " << vk::getFormatStr(m_format).toString() << ", but VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT is not" << tcu::TestLog::EndMessage;
1795 				return tcu::TestStatus::fail("VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT not supported");
1796 			}
1797 		}
1798 	}
1799 
1800 	return tcu::TestStatus::pass("Pass");
1801 }
1802 
1803 class QueryTestCase : public vkt::TestCase
1804 {
1805 public:
QueryTestCase(tcu::TestContext & context,const char * name,const vk::VkFormat format,const vk::VkImageTiling tiling)1806 	QueryTestCase(tcu::TestContext& context, const char* name, const vk::VkFormat format, const vk::VkImageTiling tiling)
1807 		: TestCase (context, name)
1808 		, m_format (format)
1809 		, m_tiling (tiling)
1810 	{
1811 	}
1812 private:
createInstance(vkt::Context & context) const1813 	vkt::TestInstance*			createInstance	(vkt::Context& context) const { return new QueryTestInstance(context, m_format, m_tiling); }
1814 	void						checkSupport	(vkt::Context& context) const;
1815 
1816 	const vk::VkFormat			m_format;
1817 	const vk::VkImageTiling		m_tiling;
1818 };
1819 
checkSupport(vkt::Context & context) const1820 void QueryTestCase::checkSupport (vkt::Context& context) const {
1821 	const InstanceInterface&				vki				= context.getInstanceInterface();
1822 
1823 	context.requireDeviceFunctionality("VK_EXT_host_image_copy");
1824 
1825 	vk::VkFormatProperties3 formatProperties3 = vk::initVulkanStructure();
1826 	vk::VkFormatProperties2 formatProperties2 = vk::initVulkanStructure(&formatProperties3);
1827 	vki.getPhysicalDeviceFormatProperties2(context.getPhysicalDevice(), m_format, &formatProperties2);
1828 	if (m_tiling == VK_IMAGE_TILING_OPTIMAL && (formatProperties3.optimalTilingFeatures & vk::VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT) == 0)
1829 		TCU_THROW(NotSupportedError, "Format feature sampled image bit not supported for optimal tiling.");
1830 	if (m_tiling == VK_IMAGE_TILING_LINEAR && (formatProperties3.linearTilingFeatures & vk::VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT) == 0)
1831 		TCU_THROW(NotSupportedError, "Format feature sampled image bit not supported for linear tiling.");
1832 }
1833 
testGenerator(tcu::TestCaseGroup * group)1834 void testGenerator(tcu::TestCaseGroup* group)
1835 {
1836 	constexpr struct CopyTest
1837 	{
1838 		bool				hostTransferLayout;
1839 		bool				copyMemoryToImage;
1840 		const char* name;
1841 	} copyTests[] =
1842 	{
1843 		// Host copy and transfer
1844 		{ true,		true,	"host_transfer_copy_general"},
1845 		// Host transfer
1846 		{ true,		false,	"host_transfer"},
1847 		// Host copy
1848 		{ false,	true,	"host_copy"},
1849 	};
1850 
1851 	constexpr struct CopyImageToMemory
1852 	{
1853 		bool			hostCopyImageToMemory;
1854 		const char* name;
1855 	} copyImageToMemoryTests[] = {
1856 		// Copy from image to memory on host
1857 		{ true,		"host_image_to_memory_copy"},
1858 		// Copy from image to memory on gpu
1859 		{ false,	"image_to_memory_copy"},
1860 	};
1861 
1862 	constexpr struct TransitionTest
1863 	{
1864 		bool		host;
1865 		const char* name;
1866 	} transitionTests[] =
1867 	{
1868 		// Transition using vkTransitionImageLayoutEXT
1869 		{ true,		"host_transition"},
1870 		// Transition using a pipeline barrier
1871 		{ false,	"barrier_transition"},
1872 	};
1873 
1874 	const struct FlagsTest
1875 	{
1876 		bool		memcpy;
1877 		const char* name;
1878 	} flagsTests[] =
1879 	{
1880 		// Copy with no flags
1881 		{ false,	"none"},
1882 		// Copy with VK_HOST_IMAGE_COPY_MEMCPY_EXT flag
1883 		{ true,		"memcpy"},
1884 	};
1885 
1886 	const struct DynamicRendering {
1887 		bool		dynamicRendering;
1888 		const char* name;
1889 	} dynamicRendering[] = {
1890 		// render pass
1891 		{ false,	"render_pass"},
1892 		// dynamic rendering
1893 		{ true,		"dynamic_rendering"},
1894 	};
1895 
1896 	const struct Tiling {
1897 		vk::VkImageTiling	tiling;
1898 		const char*			name;
1899 	} tilingTests[] = {
1900 		{ vk::VK_IMAGE_TILING_LINEAR,	"linear"},
1901 		{ vk::VK_IMAGE_TILING_OPTIMAL,	"optimal"},
1902 	};
1903 
1904 	const struct ImageFormatsAndCommand {
1905 		Command			command;
1906 		vk::VkFormat	sampled;
1907 		vk::VkFormat	output;
1908 	} formatsAndCommands[] = {
1909 		{ DRAW,		vk::VK_FORMAT_R8G8B8A8_UNORM,				vk::VK_FORMAT_R8G8B8A8_UNORM		},
1910 		{ DRAW,		vk::VK_FORMAT_R32G32B32A32_SFLOAT,			vk::VK_FORMAT_R32G32B32A32_SFLOAT	},
1911 		{ DRAW,		vk::VK_FORMAT_R16_UNORM,					vk::VK_FORMAT_R16_UNORM				},
1912 		{ DRAW,		vk::VK_FORMAT_D16_UNORM,					vk::VK_FORMAT_R16_UNORM				},
1913 		{ DRAW,		vk::VK_FORMAT_D32_SFLOAT,					vk::VK_FORMAT_R32_SFLOAT			},
1914 		{ DRAW,		vk::VK_FORMAT_BC7_UNORM_BLOCK,				vk::VK_FORMAT_R8G8B8A8_UNORM		},
1915 		{ DRAW,		vk::VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,	vk::VK_FORMAT_R8G8B8A8_UNORM		},
1916 		{ DRAW,		vk::VK_FORMAT_ASTC_4x4_UNORM_BLOCK,			vk::VK_FORMAT_R8G8B8A8_UNORM		},
1917 		{ DISPATCH,	vk::VK_FORMAT_R10X6_UNORM_PACK16,			vk::VK_FORMAT_R10X6_UNORM_PACK16	},
1918 		{ DISPATCH,	vk::VK_FORMAT_R8G8B8A8_UNORM,				vk::VK_FORMAT_R8G8B8A8_UNORM		},
1919 		{ DISPATCH,	vk::VK_FORMAT_R8G8B8A8_UNORM,				vk::VK_FORMAT_R8G8B8A8_UINT			},
1920 	};
1921 
1922 	const struct ImageSizes
1923 	{
1924 		vk::VkExtent3D	size;
1925 		const char* name;
1926 	} imageSizes[] =
1927 	{
1928 		{ makeExtent3D(16u, 16u, 1u),			"16x16"},
1929 		{ makeExtent3D(32u, 28u, 1u),			"32x28"},
1930 		{ makeExtent3D(53u, 61u, 1u),			"53x61"},
1931 	};
1932 
1933 	constexpr struct ImageLayoutTest
1934 	{
1935 		vk::VkImageLayout srcLayout;
1936 		vk::VkImageLayout dstLayout;
1937 		const char* name;
1938 	} imageLayoutTests[] =
1939 	{
1940 		{ vk::VK_IMAGE_LAYOUT_GENERAL,				vk::VK_IMAGE_LAYOUT_GENERAL,					"general_general"},
1941 		{ vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,	vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		"transfer_src_transfer_dst"},
1942 	};
1943 
1944 	constexpr struct IntermediateImageLayoutTest
1945 	{
1946 		vk::VkImageLayout layout;
1947 		const char* name;
1948 	} intermediateImageLayoutTests[] =
1949 	{
1950 		{ vk::VK_IMAGE_LAYOUT_GENERAL,							"general"},
1951 		{ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			"color_attachment_optimal"},
1952 		{ vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	"depth_stencil_attachment_optimal"},
1953 		{ vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,	"depth_stencil_read_only_optimal"},
1954 		{ vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,			"shader_read_only_optimal"},
1955 		{ vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,				"transfer_src_optimal"},
1956 		{ vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				"transfer_dst_optimal"},
1957 	};
1958 
1959 	constexpr struct SparseTest
1960 	{
1961 		bool		sparse;
1962 		const char* name;
1963 	} sparseTests[] =
1964 	{
1965 		// non-sparse image
1966 		{	false,	"regular"},
1967 		// sparse image
1968 		{	true,	"sparse"},
1969 	};
1970 
1971 	constexpr struct MipLevelRegionCountPaddingTest
1972 	{
1973 		deUint32	mipLevel;
1974 		deUint32	regionsCount;
1975 		deUint32	padding;
1976 		const char* name;
1977 		const char* desc;
1978 	} mipLevelRegionCountPaddingTests[] =
1979 	{
1980 		{	0u,		1,		0u,		"0_1_0",	""	},
1981 		{	1u,		1,		0u,		"1_1_0",	""	},
1982 		{	4u,		1,		0u,		"4_1_0",	""	},
1983 		{	0u,		4,		4u,		"0_4_4",	""	},
1984 		{	0u,		16,		64u,	"0_16_64",	""	},
1985 	};
1986 
1987 	tcu::TestContext& testCtx = group->getTestContext();
1988 
1989 	for (const auto& formatAndCommand : formatsAndCommands)
1990 	{
1991 		std::string formatName = formatAndCommand.command == DRAW ? "draw" : "dispatch";
1992 		formatName += "_" + getFormatShortString(formatAndCommand.output) + "_" + getFormatShortString(formatAndCommand.sampled);
1993 		tcu::TestCaseGroup* const formatGroup = new tcu::TestCaseGroup(testCtx, formatName.c_str());
1994 
1995 		bool colorFormat = isCompressedFormat(formatAndCommand.sampled) ||
1996 			!(tcu::hasDepthComponent(mapVkFormat(formatAndCommand.sampled).order) || tcu::hasDepthComponent(mapVkFormat(formatAndCommand.sampled).order));
1997 
1998 		for (const auto& copy : copyTests)
1999 		{
2000 			tcu::TestCaseGroup* const copyTestGroup = new tcu::TestCaseGroup(testCtx, copy.name);
2001 			for (const auto& imageToMemory : copyImageToMemoryTests)
2002 			{
2003 				tcu::TestCaseGroup* const imageToMemoryGroup = new tcu::TestCaseGroup(testCtx, imageToMemory.name);
2004 				for (const auto& transition : transitionTests)
2005 				{
2006 					tcu::TestCaseGroup* const transitionGroup = new tcu::TestCaseGroup(testCtx, transition.name);
2007 					for (const auto& flags : flagsTests)
2008 					{
2009 						tcu::TestCaseGroup* const flagsGroup = new tcu::TestCaseGroup(testCtx, flags.name);
2010 						for (const auto& layouts : imageLayoutTests)
2011 						{
2012 							tcu::TestCaseGroup* const layoutsGroup = new tcu::TestCaseGroup(testCtx, layouts.name);
2013 							for (const auto& intermediateLayout : intermediateImageLayoutTests)
2014 							{
2015 								if (colorFormat && (intermediateLayout.layout == vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || intermediateLayout.layout == vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL))
2016 									continue;
2017 								else if (!colorFormat && intermediateLayout.layout == vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
2018 									continue;
2019 
2020 								tcu::TestCaseGroup* const intermediateLayoutGroup = new tcu::TestCaseGroup(testCtx, intermediateLayout.name);
2021 								for (const auto& tiling : tilingTests)
2022 								{
2023 									tcu::TestCaseGroup* const tilingGroup = new tcu::TestCaseGroup(testCtx, tiling.name);
2024 									for (const auto& mipLevelRegionCountPaddingTest : mipLevelRegionCountPaddingTests)
2025 									{
2026 										tcu::TestCaseGroup* const mipLevelRegionCountPaddingGroup = new tcu::TestCaseGroup(testCtx, mipLevelRegionCountPaddingTest.name);
2027 										for (const auto& size : imageSizes)
2028 										{
2029 											tcu::TestCaseGroup* const sizeGroup = new tcu::TestCaseGroup(testCtx, size.name);
2030 											for (const auto& sparse : sparseTests)
2031 											{
2032 												if (sparse.sparse && isCompressedFormat(formatAndCommand.sampled))
2033 													continue;
2034 
2035 												tcu::TestCaseGroup* const sparseGroup = new tcu::TestCaseGroup(testCtx, sparse.name);
2036 												for (const auto& renderingType : dynamicRendering)
2037 												{
2038 													if (renderingType.dynamicRendering && formatAndCommand.command == DISPATCH)
2039 														continue;
2040 
2041 													const TestParameters parameters =
2042 													{
2043 														copy.copyMemoryToImage,							// bool				copyMemoryToImage
2044 														imageToMemory.hostCopyImageToMemory,			// bool				hostCopyImageToMemory
2045 														copy.hostTransferLayout,						// bool				hostTransferLayout
2046 														transition.host,								// bool				outputImageHostTransition
2047 														flags.memcpy,									// bool				memcpyFlag
2048 														renderingType.dynamicRendering,					// bool				dynamicRendering
2049 														formatAndCommand.command,						// Command			command
2050 														formatAndCommand.sampled,						// VkFormat			imageSampledFormat
2051 														layouts.srcLayout,								// VkImageLayout	srcLayout
2052 														layouts.dstLayout,								// VkImageLayout	dstLayout
2053 														intermediateLayout.layout,						// VkImageLayout	intermediateLayout
2054 														tiling.tiling,									// VkImageTiling	sampledTiling;
2055 														formatAndCommand.output,						// VkFormat			imageOutputFormat
2056 														size.size,										// VkExtent3D		imageSize
2057 														sparse.sparse,									// bool				sparse
2058 														mipLevelRegionCountPaddingTest.mipLevel,		// deUint32			mipLevel
2059 														mipLevelRegionCountPaddingTest.regionsCount,	// deUint32			regionsCount
2060 														mipLevelRegionCountPaddingTest.padding			// deUint32			padding
2061 													};
2062 
2063 													sparseGroup->addChild(new HostImageCopyTestCase(testCtx, renderingType.name, parameters));
2064 												}
2065 												sizeGroup->addChild(sparseGroup);
2066 											}
2067 											mipLevelRegionCountPaddingGroup->addChild(sizeGroup);
2068 										}
2069 										tilingGroup->addChild(mipLevelRegionCountPaddingGroup);
2070 									}
2071 									intermediateLayoutGroup->addChild(tilingGroup);
2072 								}
2073 								layoutsGroup->addChild(intermediateLayoutGroup);
2074 							}
2075 							flagsGroup->addChild(layoutsGroup);
2076 						}
2077 						transitionGroup->addChild(flagsGroup);
2078 					}
2079 					imageToMemoryGroup->addChild(transitionGroup);
2080 				}
2081 				copyTestGroup->addChild(imageToMemoryGroup);
2082 			}
2083 			formatGroup->addChild(copyTestGroup);
2084 		}
2085 		group->addChild(formatGroup);
2086 	}
2087 
2088 	const struct PreinitializedFormats {
2089 		vk::VkFormat format;
2090 	} preinitializedFormats[] = {
2091 		{ vk::VK_FORMAT_R8G8B8A8_UNORM		},
2092 		{ vk::VK_FORMAT_R32G32B32A32_SFLOAT },
2093 		{ vk::VK_FORMAT_R16_UNORM			},
2094 		{ vk::VK_FORMAT_R16G16_UINT			},
2095 		{ vk::VK_FORMAT_B8G8R8A8_SINT		},
2096 		{ vk::VK_FORMAT_R16_SFLOAT			},
2097 	};
2098 
2099 	const struct PreinitializedTiling {
2100 		vk::VkImageTiling	tiling;
2101 		const char*			name;
2102 	} preinitializedTilingTests[] = {
2103 		{ vk::VK_IMAGE_TILING_LINEAR,					"linear"},
2104 		{ vk::VK_IMAGE_TILING_OPTIMAL,					"optimal"},
2105 		{ vk::VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,	"drm_format_modifier"},
2106 	};
2107 
2108 	constexpr struct PreinitializedImageLayoutTest
2109 	{
2110 		vk::VkImageLayout layout;
2111 		const char* name;
2112 	} preinitializedImageLayoutTests[] =
2113 	{
2114 		{ vk::VK_IMAGE_LAYOUT_GENERAL,										"general"},
2115 		{ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,						"color_attachment_optimal"},
2116 		{ vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,				"depth_stencil_attachment_optimal"},
2117 		{ vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,				"depth_stencil_read_only_optimal"},
2118 		{ vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,						"shader_read_only_optimal"},
2119 		{ vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,							"transfer_src_optimal"},
2120 		{ vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,							"transfer_dst_optimal"},
2121 		{ vk::VK_IMAGE_LAYOUT_PREINITIALIZED,								"preinitialized"},
2122 		{ vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,								"present_src"},
2123 		{ vk::VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,	"depth_read_only_stencil_attachment_optimal"},
2124 		{ vk::VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,	"depth_attachment_stencil_read_only_optimal"},
2125 		{ vk::VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL,						"depth_read_only_optimal"},
2126 		{ vk::VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL,					"stencil_attachment_optimal"},
2127 		{ vk::VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL,					"stencil_read_only_optimal"},
2128 		{ vk::VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL,							"read_only_optimal"},
2129 		{ vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,							"attachment_optimal"},
2130 		{ vk::VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT,			"attachment_feedback_loop_optimal"},
2131 	};
2132 
2133 	constexpr struct ImageToImageTest
2134 	{
2135 		bool		imageToImageCopy;
2136 		bool		memcpy;
2137 		const char* name;
2138 	} imageToImageCopyTests[] =
2139 	{
2140 		{ true,		false,	"image_to_image_copy"},
2141 		{ true,		true,	"image_to_image_memcpy"},
2142 		{ false,	false,	"preinitialized"},
2143 	};
2144 
2145 	constexpr struct ImageSizeTest
2146 	{
2147 		vk::VkExtent3D	size;
2148 		deUint32		layerCount;
2149 		const char* name;
2150 	} imageSizeTests[] =
2151 	{
2152 		{ {32, 32, 1},		1,	"32x32x1_1"},
2153 		{ {32, 32, 1},		2,	"32x32x1_2"},
2154 		{ {51, 63, 1},		1,	"51x63x1_1"},
2155 		{ {24, 24, 4},		1,	"24x24x4_4"},
2156 	};
2157 
2158 	for (const auto& tiling : preinitializedTilingTests)
2159 	{
2160 		tcu::TestCaseGroup* const tilingGroup = new tcu::TestCaseGroup(testCtx, tiling.name);
2161 		for (const auto& imageToImage : imageToImageCopyTests)
2162 		{
2163 			tcu::TestCaseGroup* const imageToImageCopyGroup = new tcu::TestCaseGroup(testCtx, imageToImage.name);
2164 			for (const auto& srcLayout : preinitializedImageLayoutTests)
2165 			{
2166 				tcu::TestCaseGroup* const srcLayoutGroup = new tcu::TestCaseGroup(testCtx, srcLayout.name);
2167 				for (const auto& dstLayout : preinitializedImageLayoutTests)
2168 				{
2169 					tcu::TestCaseGroup* const dstLayoutGroup = new tcu::TestCaseGroup(testCtx, dstLayout.name);
2170 					for (const auto& size : imageSizeTests)
2171 					{
2172 						tcu::TestCaseGroup* const sizeGroup = new tcu::TestCaseGroup(testCtx, size.name);
2173 						for (const auto& format : preinitializedFormats)
2174 						{
2175 							const auto formatName = getFormatShortString(format.format);
2176 							sizeGroup->addChild(new PreinitializedTestCase(testCtx, formatName.c_str(), format.format, srcLayout.layout, dstLayout.layout, size.size, size.layerCount, imageToImage.imageToImageCopy, imageToImage.memcpy, tiling.tiling));
2177 						}
2178 						dstLayoutGroup->addChild(sizeGroup);
2179 					}
2180 					srcLayoutGroup->addChild(dstLayoutGroup);
2181 				}
2182 				imageToImageCopyGroup->addChild(srcLayoutGroup);
2183 			}
2184 			tilingGroup->addChild(imageToImageCopyGroup);
2185 		}
2186 		group->addChild(tilingGroup);
2187 	}
2188 
2189 	tcu::TestCaseGroup* const propertiesGroup = new tcu::TestCaseGroup(testCtx, "properties");
2190 	propertiesGroup->addChild(new PropertiesTestCase(testCtx, "properties"));
2191 
2192 	const struct QueryFormats {
2193 		vk::VkFormat format;
2194 	} queryFormats[] = {
2195 		{ vk::VK_FORMAT_R8G8B8A8_UNORM		},
2196 		{ vk::VK_FORMAT_R32G32B32A32_SFLOAT },
2197 		{ vk::VK_FORMAT_R16_UNORM			},
2198 		{ vk::VK_FORMAT_R16G16_UINT			},
2199 		{ vk::VK_FORMAT_B8G8R8A8_SINT		},
2200 		{ vk::VK_FORMAT_R16_SFLOAT			},
2201 		{ vk::VK_FORMAT_D24_UNORM_S8_UINT	},
2202 		{ vk::VK_FORMAT_BC7_UNORM_BLOCK		},
2203 		{ vk::VK_FORMAT_BC5_SNORM_BLOCK		},
2204 	};
2205 
2206 	group->addChild(propertiesGroup);
2207 
2208 	tcu::TestCaseGroup* const queryGroup = new tcu::TestCaseGroup(testCtx, "query");
2209 
2210 	for (const auto& tiling : tilingTests)
2211 	{
2212 		tcu::TestCaseGroup* const tilingGroup = new tcu::TestCaseGroup(testCtx, tiling.name);
2213 		for (const auto& format : queryFormats)
2214 		{
2215 			const auto formatName = getFormatShortString(format.format);
2216 			tilingGroup->addChild(new QueryTestCase(testCtx, formatName.c_str(), format.format, tiling.tiling));
2217 		}
2218 		queryGroup->addChild(tilingGroup);
2219 	}
2220 
2221 	group->addChild(queryGroup);
2222 }
2223 
2224 } // anonymous
2225 
createImageHostImageCopyTests(tcu::TestContext & testCtx)2226 tcu::TestCaseGroup* createImageHostImageCopyTests (tcu::TestContext& testCtx)
2227 {
2228 	de::MovePtr<tcu::TestCaseGroup> testGroup (createTestGroup(testCtx, "host_image_copy", testGenerator));
2229 	return testGroup.release();
2230 }
2231 
2232 } // image
2233 } // vkt
2234