1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Tests for mutable images
22 *//*--------------------------------------------------------------------*/
23
24#include "vktImageMutableTests.hpp"
25#include "vktImageLoadStoreUtil.hpp"
26#include "vktTestCaseUtil.hpp"
27#include "vktImageTexture.hpp"
28
29#include "vkBuilderUtil.hpp"
30#include "vkQueryUtil.hpp"
31#include "vkImageUtil.hpp"
32
33#include "deUniquePtr.hpp"
34#include "deSharedPtr.hpp"
35
36#include "tcuImageCompare.hpp"
37#include "tcuTestLog.hpp"
38#include "tcuTextureUtil.hpp"
39
40#include <string>
41#include <vector>
42
43using namespace vk;
44using namespace tcu;
45
46using de::UniquePtr;
47using de::MovePtr;
48using de::SharedPtr;
49using std::vector;
50
51namespace vkt
52{
53namespace image
54{
55
56typedef SharedPtr<Unique<VkPipeline> >	SharedPtrVkPipeline;
57typedef SharedPtr<Unique<VkImageView> >	SharedPtrVkImageView;
58
59template<typename T>
60inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
61{
62	return SharedPtr<Unique<T> >(new Unique<T>(move));
63}
64
65enum Upload {
66	UPLOAD_CLEAR = 0,
67	UPLOAD_COPY,
68	UPLOAD_STORE,
69	UPLOAD_DRAW,
70	UPLOAD_LAST
71};
72
73enum Download {
74	DOWNLOAD_COPY = 0,
75	DOWNLOAD_LOAD,
76	DOWNLOAD_TEXTURE,
77	DOWNLOAD_LAST
78};
79
80std::string getUploadString (const int upload)
81{
82	const char* strs[] = { "clear", "copy", "store", "draw" };
83	return strs[upload];
84}
85
86std::string getDownloadString (const int download)
87{
88	const char* strs[] = { "copy", "load", "texture" };
89	return strs[download];
90}
91
92struct CaseDef
93{
94	ImageType		imageType;
95	IVec3			size;
96	deUint32		numLayers;
97	VkFormat		imageFormat;
98	VkFormat		viewFormat;
99	enum Upload		upload;
100	enum Download	download;
101	bool			isFormatListTest;
102};
103
104static const deUint32 COLOR_TABLE_SIZE = 4;
105
106// Reference color values for float color rendering. Values have been chosen
107// so that when the bit patterns are reinterpreted as a 16-bit float, we do not
108// run into NaN / inf / denorm values.
109static const Vec4	COLOR_TABLE_FLOAT[COLOR_TABLE_SIZE]	=
110{
111	Vec4(0.00f, 0.40f, 0.80f, 0.10f),
112	Vec4(0.50f, 0.10f, 0.90f, 0.20f),
113	Vec4(0.20f, 0.60f, 1.00f, 0.30f),
114	Vec4(0.30f, 0.70f, 0.00f, 0.40f),
115};
116
117// Reference color values for integer color rendering. We avoid negative
118// values (even for SINT formats) to avoid the situation where sign extension
119// leads to NaN / inf values when they are reinterpreted with a float
120// format.
121static const IVec4	COLOR_TABLE_INT[COLOR_TABLE_SIZE]	=
122{
123	IVec4(112,  60,	101,  41),
124	IVec4( 60, 101,	 41, 112),
125	IVec4( 41, 112,	 60, 101),
126	IVec4(101,  41,	112,  60),
127};
128
129// Reference clear colors created from the color table values
130static const VkClearValue REFERENCE_CLEAR_COLOR_FLOAT[COLOR_TABLE_SIZE]	=
131{
132	makeClearValueColorF32(COLOR_TABLE_FLOAT[0].x(), COLOR_TABLE_FLOAT[0].y(), COLOR_TABLE_FLOAT[0].z(), COLOR_TABLE_FLOAT[0].w()),
133	makeClearValueColorF32(COLOR_TABLE_FLOAT[1].x(), COLOR_TABLE_FLOAT[1].y(), COLOR_TABLE_FLOAT[1].z(), COLOR_TABLE_FLOAT[1].w()),
134	makeClearValueColorF32(COLOR_TABLE_FLOAT[2].x(), COLOR_TABLE_FLOAT[2].y(), COLOR_TABLE_FLOAT[2].z(), COLOR_TABLE_FLOAT[2].w()),
135	makeClearValueColorF32(COLOR_TABLE_FLOAT[3].x(), COLOR_TABLE_FLOAT[3].y(), COLOR_TABLE_FLOAT[3].z(), COLOR_TABLE_FLOAT[3].w()),
136};
137
138static const VkClearValue REFERENCE_CLEAR_COLOR_INT[COLOR_TABLE_SIZE]	=
139{
140	makeClearValueColorI32(COLOR_TABLE_INT[0].x(), COLOR_TABLE_INT[0].y(), COLOR_TABLE_INT[0].z(), COLOR_TABLE_INT[0].w()),
141	makeClearValueColorI32(COLOR_TABLE_INT[1].x(), COLOR_TABLE_INT[1].y(), COLOR_TABLE_INT[1].z(), COLOR_TABLE_INT[1].w()),
142	makeClearValueColorI32(COLOR_TABLE_INT[2].x(), COLOR_TABLE_INT[2].y(), COLOR_TABLE_INT[2].z(), COLOR_TABLE_INT[2].w()),
143	makeClearValueColorI32(COLOR_TABLE_INT[3].x(), COLOR_TABLE_INT[3].y(), COLOR_TABLE_INT[3].z(), COLOR_TABLE_INT[3].w()),
144};
145
146static const Texture s_textures[] =
147{
148	Texture(IMAGE_TYPE_2D,			tcu::IVec3(32, 32, 1),	1),
149	Texture(IMAGE_TYPE_2D_ARRAY,	tcu::IVec3(32, 32, 1),	4),
150};
151
152VkImageType getImageType (const ImageType textureImageType)
153{
154	switch (textureImageType)
155	{
156		case IMAGE_TYPE_2D:
157		case IMAGE_TYPE_2D_ARRAY:
158			return VK_IMAGE_TYPE_2D;
159
160		default:
161			DE_ASSERT(0);
162			return VK_IMAGE_TYPE_LAST;
163	}
164}
165
166VkImageViewType getImageViewType (const ImageType textureImageType)
167{
168	switch (textureImageType)
169	{
170		case IMAGE_TYPE_2D:
171			return VK_IMAGE_VIEW_TYPE_2D;
172		case IMAGE_TYPE_2D_ARRAY:
173			return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
174
175		default:
176			DE_ASSERT(0);
177			return VK_IMAGE_VIEW_TYPE_LAST;
178	}
179}
180
181static const VkFormat s_formats[] =
182{
183	VK_FORMAT_R32G32B32A32_SFLOAT,
184	VK_FORMAT_R16G16B16A16_SFLOAT,
185	VK_FORMAT_R32G32_SFLOAT,
186	VK_FORMAT_R16G16_SFLOAT,
187	VK_FORMAT_R32_SFLOAT,
188
189	VK_FORMAT_R32G32B32A32_UINT,
190	VK_FORMAT_R16G16B16A16_UINT,
191	VK_FORMAT_R8G8B8A8_UINT,
192	VK_FORMAT_R32G32_UINT,
193	VK_FORMAT_R16G16_UINT,
194	VK_FORMAT_R32_UINT,
195
196	VK_FORMAT_R32G32B32A32_SINT,
197	VK_FORMAT_R16G16B16A16_SINT,
198	VK_FORMAT_R8G8B8A8_SINT,
199	VK_FORMAT_R32G32_SINT,
200	VK_FORMAT_R16G16_SINT,
201	VK_FORMAT_R32_SINT,
202
203	VK_FORMAT_R8G8B8A8_UNORM,
204
205	VK_FORMAT_R8G8B8A8_SNORM,
206};
207
208inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
209{
210	return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
211}
212
213std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
214{
215	std::ostringstream str;
216	if (numComponents == 1)
217		str << (isUint ? "uint" : isSint ? "int" : "float");
218	else
219		str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
220
221	return str.str();
222}
223
224std::string getShaderSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
225{
226	std::ostringstream samplerType;
227
228	if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
229		samplerType << "u";
230	else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
231		samplerType << "i";
232
233	switch (type)
234	{
235		case VK_IMAGE_VIEW_TYPE_2D:
236			samplerType << "sampler2D";
237			break;
238
239		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
240			samplerType << "sampler2DArray";
241			break;
242
243		default:
244			DE_FATAL("Ivalid image view type");
245			break;
246	}
247
248	return samplerType.str();
249}
250
251void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
252{
253	if (caseDef.upload == UPLOAD_DRAW)
254	{
255		{
256			std::ostringstream src;
257			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
258				<< "\n"
259				<< "layout(location = 0) in  vec4 in_position;\n"
260				<< "layout(location = 1) in  vec4 in_color;\n"
261				<< "layout(location = 0) out vec4 out_color;\n"
262				<< "\n"
263				<< "out gl_PerVertex {\n"
264				<< "	vec4 gl_Position;\n"
265				<< "};\n"
266				<< "\n"
267				<< "void main(void)\n"
268				<< "{\n"
269				<< "	gl_Position	= in_position;\n"
270				<< "	out_color	= in_color;\n"
271				<< "}\n";
272
273			programCollection.glslSources.add("uploadDrawVert") << glu::VertexSource(src.str());
274		}
275
276		{
277			const int	numComponents		= getNumUsedChannels(mapVkFormat(caseDef.viewFormat).order);
278			const bool	isUint				= isUintFormat(caseDef.viewFormat);
279			const bool	isSint				= isIntFormat(caseDef.viewFormat);
280			const std::string colorFormat	= getColorFormatStr(numComponents, isUint, isSint);
281
282			std::ostringstream src;
283			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
284				<< "\n"
285				<< "layout(location = 0) in  vec4 in_color;\n"
286				<< "layout(location = 0) out " << colorFormat << " out_color;\n"
287				<< "\n"
288				<< "void main(void)\n"
289				<< "{\n"
290				<< "    out_color = " << colorFormat << "("
291				<< (numComponents == 1 ? "in_color.r"   :
292					numComponents == 2 ? "in_color.rg"  :
293					numComponents == 3 ? "in_color.rgb" : "in_color")
294				<< ");\n"
295				<< "}\n";
296
297			programCollection.glslSources.add("uploadDrawFrag") << glu::FragmentSource(src.str());
298		}
299	}
300
301	if (caseDef.upload == UPLOAD_STORE)
302	{
303		const TextureFormat	tcuFormat		= mapVkFormat(caseDef.viewFormat);
304		const std::string	imageFormatStr	= getShaderImageFormatQualifier(tcuFormat);
305		const std::string	imageTypeStr	= getShaderImageType(tcuFormat, caseDef.imageType);
306		const std::string	colorTypeStr	= isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
307		const bool			isIntegerFormat	= isUintFormat(caseDef.viewFormat) || isIntFormat(caseDef.viewFormat);
308
309		std::ostringstream src;
310		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
311			<< "\n"
312			<< "layout (local_size_x = 1) in;\n"
313			<< "\n"
314			<< "layout(binding=0, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " u_image;\n"
315			<< "\n"
316			<< "const " << colorTypeStr << " colorTable[] = " << colorTypeStr << "[](\n";
317		for (deUint32 idx = 0; idx < COLOR_TABLE_SIZE; idx++)
318		{
319			if (isIntegerFormat)
320				src << "     " << colorTypeStr << "(" << COLOR_TABLE_INT[idx].x() << ", " << COLOR_TABLE_INT[idx].y() << ", " << COLOR_TABLE_INT[idx].z() << ", " << COLOR_TABLE_INT[idx].w() << ")";
321			else
322				src << "     " << colorTypeStr << "(" << COLOR_TABLE_FLOAT[idx].x() << ", " << COLOR_TABLE_FLOAT[idx].y() << ", " << COLOR_TABLE_FLOAT[idx].z() << ", " << COLOR_TABLE_FLOAT[idx].w() << ")";
323			if (idx < COLOR_TABLE_SIZE - 1)
324				src << ",";
325			src << "\n";
326		}
327		src << ");\n"
328			<< "\n"
329			<< "void main(void)\n"
330			<< "{\n";
331		if (caseDef.imageType == IMAGE_TYPE_2D)
332		{
333			src	<< "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
334		}
335		else
336		{
337			DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
338			src	<< "    ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
339		}
340		src << "    " << colorTypeStr << " color = colorTable[gl_GlobalInvocationID.z];\n"
341			<< "    imageStore(u_image, pos, color);\n"
342			<< "}\n";
343
344		programCollection.glslSources.add("uploadStoreComp") << glu::ComputeSource(src.str());
345	}
346
347	if (caseDef.download == DOWNLOAD_LOAD)
348	{
349		const TextureFormat	tcuFormat		= mapVkFormat(caseDef.viewFormat);
350		const std::string	imageFormatStr	= getShaderImageFormatQualifier(tcuFormat);
351		const std::string	imageTypeStr	= getShaderImageType(tcuFormat, caseDef.imageType);
352		const std::string	colorTypeStr	= isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
353
354		std::ostringstream src;
355		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
356			<< "\n"
357			<< "layout (local_size_x = 1) in;\n"
358			<< "\n"
359			<< "layout(binding=0, " << imageFormatStr << ") readonly uniform " << imageTypeStr << " in_image;\n"
360			<< "layout(binding=1, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " out_image;\n"
361			<< "\n"
362			<< "void main(void)\n"
363			<< "{\n";
364		if (caseDef.imageType == IMAGE_TYPE_2D)
365		{
366			src	<< "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
367		}
368		else
369		{
370			DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
371			src	<< "    ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
372		}
373		src	<< "    imageStore(out_image, pos, imageLoad(in_image, pos));\n"
374			<< "}\n";
375
376		programCollection.glslSources.add("downloadLoadComp") << glu::ComputeSource(src.str());
377	}
378
379	if (caseDef.download == DOWNLOAD_TEXTURE)
380	{
381		const TextureFormat		tcuFormat		= mapVkFormat(caseDef.viewFormat);
382		const VkImageViewType	viewType		= getImageViewType(caseDef.imageType);
383		const std::string		samplerTypeStr	= getShaderSamplerType(tcuFormat, viewType);
384		const std::string		imageFormatStr	= getShaderImageFormatQualifier(tcuFormat);
385		const std::string		imageTypeStr	= getShaderImageType(tcuFormat, caseDef.imageType);
386		const std::string		colorTypeStr	= isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
387
388		std::ostringstream src;
389		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
390			<< "\n"
391			<< "layout (local_size_x = 1) in;\n"
392			<< "\n"
393			<< "layout(binding=0) uniform " << samplerTypeStr << " u_tex;\n"
394			<< "layout(binding=1, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " out_image;\n"
395			<< "\n"
396			<< "void main(void)\n"
397			<< "{\n";
398		if (caseDef.imageType == IMAGE_TYPE_2D)
399		{
400			src	<< "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
401		}
402		else
403		{
404			DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
405			src	<< "    ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
406		}
407		src	<< "    imageStore(out_image, pos, texelFetch(u_tex, pos, 0));\n"
408			<< "}\n";
409
410		programCollection.glslSources.add("downloadTextureComp") << glu::ComputeSource(src.str());
411	}
412}
413
414Move<VkImage> makeImage (const DeviceInterface&		vk,
415						 const VkDevice				device,
416						 VkImageCreateFlags			flags,
417						 VkImageType				imageType,
418						 const VkFormat				format,
419						 const VkFormat				viewFormat,
420						 const bool					useImageFormatList,
421						 const IVec3&				size,
422						 const deUint32				numMipLevels,
423						 const deUint32				numLayers,
424						 const VkImageUsageFlags	usage)
425{
426	const VkFormat formatList[2] =
427	{
428		format,
429		viewFormat
430	};
431
432	const VkImageFormatListCreateInfoKHR formatListInfo =
433	{
434		VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR,	// VkStructureType			sType;
435		DE_NULL,												// const void*				pNext;
436		2u,														// deUint32					viewFormatCount
437		formatList												// const VkFormat*			pViewFormats
438	};
439
440	const VkImageCreateInfo imageParams =
441	{
442		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType;
443		useImageFormatList ? &formatListInfo : DE_NULL,			// const void*				pNext;
444		flags,													// VkImageCreateFlags		flags;
445		imageType,												// VkImageType				imageType;
446		format,													// VkFormat					format;
447		makeExtent3D(size),										// VkExtent3D				extent;
448		numMipLevels,											// deUint32					mipLevels;
449		numLayers,												// deUint32					arrayLayers;
450		VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits	samples;
451		VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling;
452		usage,													// VkImageUsageFlags		usage;
453		VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode			sharingMode;
454		0u,														// deUint32					queueFamilyIndexCount;
455		DE_NULL,												// const deUint32*			pQueueFamilyIndices;
456		VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			initialLayout;
457	};
458	return createImage(vk, device, &imageParams);
459}
460
461inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
462{
463	const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
464	return createBuffer(vk, device, &bufferCreateInfo);
465}
466
467inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
468{
469	return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
470}
471
472Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
473{
474	const VkSamplerCreateInfo samplerParams =
475	{
476		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType			sType;
477		DE_NULL,									// const void*				pNext;
478		(VkSamplerCreateFlags)0,					// VkSamplerCreateFlags		flags;
479		VK_FILTER_NEAREST,							// VkFilter					magFilter;
480		VK_FILTER_NEAREST,							// VkFilter					minFilter;
481		VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode		mipmapMode;
482		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeU;
483		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeV;
484		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeW;
485		0.0f,										// float					mipLodBias;
486		VK_FALSE,									// VkBool32					anisotropyEnable;
487		1.0f,										// float					maxAnisotropy;
488		VK_FALSE,									// VkBool32					compareEnable;
489		VK_COMPARE_OP_ALWAYS,						// VkCompareOp				compareOp;
490		0.0f,										// float					minLod;
491		0.0f,										// float					maxLod;
492		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// VkBorderColor			borderColor;
493		VK_FALSE,									// VkBool32					unnormalizedCoordinates;
494	};
495
496	return createSampler(vk, device, &samplerParams);
497}
498
499
500Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&	vk,
501										   const VkDevice			device)
502{
503	const VkPipelineLayoutCreateInfo info =
504	{
505		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
506		DE_NULL,
507		(VkPipelineLayoutCreateFlags)0,
508		0u,
509		DE_NULL,
510		0u,
511		DE_NULL,
512	};
513	return createPipelineLayout(vk, device, &info);
514}
515
516Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
517									   const VkDevice				device,
518									   const VkPipelineLayout		pipelineLayout,
519									   const VkRenderPass			renderPass,
520									   const VkShaderModule			vertexModule,
521									   const VkShaderModule			fragmentModule,
522									   const IVec2&					renderSize,
523									   const VkPrimitiveTopology	topology,
524									   const deUint32				subpass)
525{
526	const VkVertexInputBindingDescription vertexInputBindingDescription =
527	{
528		0u,									// deUint32				binding;
529		(deUint32)(2 * sizeof(Vec4)),		// deUint32				stride;
530		VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate	inputRate;
531	};
532
533	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
534	{
535		{
536			0u,								// deUint32			location;
537			0u,								// deUint32			binding;
538			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat			format;
539			0u,								// deUint32			offset;
540		},
541		{
542			1u,								// deUint32			location;
543			0u,								// deUint32			binding;
544			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat			format;
545			(deUint32)sizeof(Vec4),			// deUint32			offset;
546		}
547	};
548
549	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
550	{
551		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
552		DE_NULL,													// const void*								pNext;
553		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags	flags;
554		1u,															// deUint32									vertexBindingDescriptionCount;
555		&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
556		DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),		// deUint32									vertexAttributeDescriptionCount;
557		vertexInputAttributeDescriptions,							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
558	};
559
560	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
561	{
562		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
563		DE_NULL,														// const void*								pNext;
564		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags	flags;
565		topology,														// VkPrimitiveTopology						topology;
566		VK_FALSE,														// VkBool32									primitiveRestartEnable;
567	};
568
569	const VkViewport viewport = makeViewport(
570		0.0f, 0.0f,
571		static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
572		0.0f, 1.0f);
573
574	const VkRect2D scissor =
575	{
576		makeOffset2D(0, 0),
577		makeExtent2D(renderSize.x(), renderSize.y()),
578	};
579
580	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
581	{
582		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,		// VkStructureType						sType;
583		DE_NULL,													// const void*							pNext;
584		(VkPipelineViewportStateCreateFlags)0,						// VkPipelineViewportStateCreateFlags	flags;
585		1u,															// deUint32								viewportCount;
586		&viewport,													// const VkViewport*					pViewports;
587		1u,															// deUint32								scissorCount;
588		&scissor,													// const VkRect2D*						pScissors;
589	};
590
591	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
592	{
593		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType;
594		DE_NULL,													// const void*								pNext;
595		(VkPipelineRasterizationStateCreateFlags)0,					// VkPipelineRasterizationStateCreateFlags	flags;
596		VK_FALSE,													// VkBool32									depthClampEnable;
597		VK_FALSE,													// VkBool32									rasterizerDiscardEnable;
598		VK_POLYGON_MODE_FILL,										// VkPolygonMode							polygonMode;
599		VK_CULL_MODE_NONE,											// VkCullModeFlags							cullMode;
600		VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace;
601		VK_FALSE,													// VkBool32									depthBiasEnable;
602		0.0f,														// float									depthBiasConstantFactor;
603		0.0f,														// float									depthBiasClamp;
604		0.0f,														// float									depthBiasSlopeFactor;
605		1.0f,														// float									lineWidth;
606	};
607
608	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
609	{
610		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
611		DE_NULL,													// const void*								pNext;
612		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
613		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
614		VK_FALSE,													// VkBool32									sampleShadingEnable;
615		0.0f,														// float									minSampleShading;
616		DE_NULL,													// const VkSampleMask*						pSampleMask;
617		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
618		VK_FALSE													// VkBool32									alphaToOneEnable;
619	};
620
621	const VkStencilOpState stencilOpState = makeStencilOpState(
622		VK_STENCIL_OP_KEEP,											// stencil fail
623		VK_STENCIL_OP_ZERO,											// depth & stencil pass
624		VK_STENCIL_OP_KEEP,											// depth only fail
625		VK_COMPARE_OP_EQUAL,										// compare op
626		~0u,														// compare mask
627		~0u,														// write mask
628		0u);														// reference
629
630	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
631	{
632		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
633		DE_NULL,													// const void*								pNext;
634		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
635		VK_FALSE,													// VkBool32									depthTestEnable;
636		VK_FALSE,													// VkBool32									depthWriteEnable;
637		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
638		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
639		VK_FALSE,													// VkBool32									stencilTestEnable;
640		stencilOpState,												// VkStencilOpState							front;
641		stencilOpState,												// VkStencilOpState							back;
642		0.0f,														// float									minDepthBounds;
643		1.0f,														// float									maxDepthBounds;
644	};
645
646	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
647	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
648	{
649		VK_FALSE,													// VkBool32					blendEnable;
650		VK_BLEND_FACTOR_ONE,										// VkBlendFactor			srcColorBlendFactor;
651		VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			dstColorBlendFactor;
652		VK_BLEND_OP_ADD,											// VkBlendOp				colorBlendOp;
653		VK_BLEND_FACTOR_ONE,										// VkBlendFactor			srcAlphaBlendFactor;
654		VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			dstAlphaBlendFactor;
655		VK_BLEND_OP_ADD,											// VkBlendOp				alphaBlendOp;
656		colorComponentsAll,											// VkColorComponentFlags	colorWriteMask;
657	};
658
659	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
660	{
661		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
662		DE_NULL,													// const void*									pNext;
663		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
664		VK_FALSE,													// VkBool32										logicOpEnable;
665		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
666		1u,															// deUint32										attachmentCount;
667		&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
668		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
669	};
670
671	const VkPipelineShaderStageCreateInfo pShaderStages[] =
672	{
673		{
674			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
675			DE_NULL,												// const void*							pNext;
676			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
677			VK_SHADER_STAGE_VERTEX_BIT,								// VkShaderStageFlagBits				stage;
678			vertexModule,											// VkShaderModule						module;
679			"main",													// const char*							pName;
680			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
681		},
682		{
683			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
684			DE_NULL,												// const void*							pNext;
685			(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
686			VK_SHADER_STAGE_FRAGMENT_BIT,							// VkShaderStageFlagBits				stage;
687			fragmentModule,											// VkShaderModule						module;
688			"main",													// const char*							pName;
689			DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
690		}
691	};
692
693	const VkGraphicsPipelineCreateInfo	graphicsPipelineInfo =
694	{
695		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
696		DE_NULL,											// const void*										pNext;
697		0u,													// VkPipelineCreateFlags							flags;
698		DE_LENGTH_OF_ARRAY(pShaderStages),					// deUint32											stageCount;
699		pShaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
700		&vertexInputStateInfo,								// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
701		&pipelineInputAssemblyStateInfo,					// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
702		DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
703		&pipelineViewportStateInfo,							// const VkPipelineViewportStateCreateInfo*			pViewportState;
704		&pipelineRasterizationStateInfo,					// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
705		&pipelineMultisampleStateInfo,						// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
706		&pipelineDepthStencilStateInfo,						// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
707		&pipelineColorBlendStateInfo,						// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
708		DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
709		pipelineLayout,										// VkPipelineLayout									layout;
710		renderPass,											// VkRenderPass										renderPass;
711		subpass,											// deUint32											subpass;
712		DE_NULL,											// VkPipeline										basePipelineHandle;
713		0,													// deInt32											basePipelineIndex;
714	};
715
716	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
717}
718
719Move<VkPipeline> makeComputePipeline (const DeviceInterface&		vk,
720									  const VkDevice				device,
721									  const VkPipelineLayout		pipelineLayout,
722									  const VkShaderModule			shaderModule,
723									  const VkSpecializationInfo*	specInfo)
724{
725	const VkPipelineShaderStageCreateInfo shaderStageInfo =
726	{
727		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
728		DE_NULL,												// const void*						pNext;
729		(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags	flags;
730		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits			stage;
731		shaderModule,											// VkShaderModule					module;
732		"main",													// const char*						pName;
733		specInfo,												// const VkSpecializationInfo*		pSpecializationInfo;
734	};
735	const VkComputePipelineCreateInfo pipelineInfo =
736	{
737		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType					sType;
738		DE_NULL,												// const void*						pNext;
739		(VkPipelineCreateFlags)0,								// VkPipelineCreateFlags			flags;
740		shaderStageInfo,										// VkPipelineShaderStageCreateInfo	stage;
741		pipelineLayout,											// VkPipelineLayout					layout;
742		DE_NULL,												// VkPipeline						basePipelineHandle;
743		0,														// deInt32							basePipelineIndex;
744	};
745	return createComputePipeline(vk, device, DE_NULL , &pipelineInfo);
746}
747
748Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
749								   const VkDevice			device,
750								   const VkFormat			colorFormat,
751								   const deUint32			numLayers)
752{
753	const VkAttachmentDescription colorAttachmentDescription =
754	{
755		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
756		colorFormat,										// VkFormat							format;
757		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
758		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
759		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
760		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
761		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
762		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
763		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
764	};
765	vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
766
767	// Create a subpass for each attachment (each attachement is a layer of an arrayed image).
768	vector<VkAttachmentReference>	colorAttachmentReferences	(numLayers);
769	vector<VkSubpassDescription>	subpasses;
770
771	// Ordering here must match the framebuffer attachments
772	for (deUint32 i = 0; i < numLayers; ++i)
773	{
774		const VkAttachmentReference attachmentRef =
775		{
776			i,													// deUint32			attachment;
777			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
778		};
779
780		colorAttachmentReferences[i]	= attachmentRef;
781
782		const VkSubpassDescription		subpassDescription	=
783		{
784			(VkSubpassDescriptionFlags)0,					// VkSubpassDescriptionFlags		flags;
785			VK_PIPELINE_BIND_POINT_GRAPHICS,				// VkPipelineBindPoint				pipelineBindPoint;
786			0u,												// deUint32							inputAttachmentCount;
787			DE_NULL,										// const VkAttachmentReference*		pInputAttachments;
788			1u,												// deUint32							colorAttachmentCount;
789			&colorAttachmentReferences[i],					// const VkAttachmentReference*		pColorAttachments;
790			DE_NULL,										// const VkAttachmentReference*		pResolveAttachments;
791			DE_NULL,										// const VkAttachmentReference*		pDepthStencilAttachment;
792			0u,												// deUint32							preserveAttachmentCount;
793			DE_NULL											// const deUint32*					pPreserveAttachments;
794		};
795		subpasses.push_back(subpassDescription);
796	}
797
798	const VkRenderPassCreateInfo renderPassInfo =
799	{
800		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// VkStructureType					sType;
801		DE_NULL,												// const void*						pNext;
802		(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags;
803		static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount;
804		&attachmentDescriptions[0],								// const VkAttachmentDescription*	pAttachments;
805		static_cast<deUint32>(subpasses.size()),				// deUint32							subpassCount;
806		&subpasses[0],											// const VkSubpassDescription*		pSubpasses;
807		0u,														// deUint32							dependencyCount;
808		DE_NULL													// const VkSubpassDependency*		pDependencies;
809	};
810
811	return createRenderPass(vk, device, &renderPassInfo);
812}
813
814Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&	vk,
815									 const VkDevice			device,
816									 const VkRenderPass		renderPass,
817									 const deUint32			attachmentCount,
818									 const VkImageView*		pAttachments,
819									 const IVec2			size)
820{
821	const VkFramebufferCreateInfo framebufferInfo =
822	{
823		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
824		DE_NULL,
825		(VkFramebufferCreateFlags)0,
826		renderPass,
827		attachmentCount,
828		pAttachments,
829		static_cast<deUint32>(size.x()),
830		static_cast<deUint32>(size.y()),
831		1u,
832	};
833
834	return createFramebuffer(vk, device, &framebufferInfo);
835}
836
837Move<VkCommandBuffer> makeCommandBuffer	(const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
838{
839	return allocateCommandBuffer(vk, device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
840}
841
842MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement)
843{
844        MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement);
845        VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset()));
846        return alloc;
847}
848
849MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBuffer buffer, const MemoryRequirement requirement)
850{
851        MovePtr<Allocation> alloc(allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), requirement));
852        VK_CHECK(vk.bindBufferMemory(device, buffer, alloc->getMemory(), alloc->getOffset()));
853        return alloc;
854}
855
856vector<Vec4> genVertexData (const CaseDef& caseDef)
857{
858	vector<Vec4>	vectorData;
859	const bool		isIntegerFormat	= isUintFormat(caseDef.viewFormat) || isIntFormat(caseDef.viewFormat);
860
861	for (deUint32 z = 0; z < caseDef.numLayers; z++)
862	{
863		const deUint32	colorIdx	= z % COLOR_TABLE_SIZE;
864		const Vec4		color		= isIntegerFormat ? COLOR_TABLE_INT[colorIdx].cast<float>() : COLOR_TABLE_FLOAT[colorIdx];
865
866		vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
867		vectorData.push_back(color);
868		vectorData.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
869		vectorData.push_back(color);
870		vectorData.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
871		vectorData.push_back(color);
872		vectorData.push_back(Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
873		vectorData.push_back(color);
874	}
875
876	return vectorData;
877}
878
879void generateExpectedImage(const tcu::PixelBufferAccess& image, const CaseDef& caseDef)
880{
881	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(image.getFormat().type);
882	const bool						isIntegerFormat	= channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
883	const IVec2						size			= caseDef.size.swizzle(0, 1);
884
885	for (int z = 0; z < static_cast<int>(caseDef.numLayers); z++)
886	{
887		const deUint32	colorIdx	= z % COLOR_TABLE_SIZE;
888		for (int y = 0; y < size.y(); y++)
889		for (int x = 0; x < size.x(); x++)
890		{
891			if (isIntegerFormat)
892				image.setPixel(COLOR_TABLE_INT[colorIdx], x, y, z);
893			else
894				image.setPixel(COLOR_TABLE_FLOAT[colorIdx], x, y, z);
895		}
896	}
897}
898
899VkImageUsageFlags getImageUsageForTestCase (const CaseDef& caseDef)
900{
901	VkImageUsageFlags flags = 0u;
902
903	switch (caseDef.upload)
904	{
905	case UPLOAD_CLEAR:
906		flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
907		break;
908	case UPLOAD_DRAW:
909		flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
910		break;
911	case UPLOAD_STORE:
912		flags |= VK_IMAGE_USAGE_STORAGE_BIT;
913		break;
914	case UPLOAD_COPY:
915		flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
916		break;
917	default:
918		DE_ASSERT("Invalid upload method");
919		break;
920	}
921
922	switch (caseDef.download)
923	{
924	case DOWNLOAD_TEXTURE:
925		flags |= VK_IMAGE_USAGE_SAMPLED_BIT;
926		break;
927	case DOWNLOAD_LOAD:
928		flags |= VK_IMAGE_USAGE_STORAGE_BIT;
929		break;
930	case DOWNLOAD_COPY:
931		flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
932		break;
933	default:
934		DE_ASSERT("Invalid download method");
935		break;
936	}
937
938	// We can only create a view for the image if it is going to be used for any of these usages,
939	// so let's make sure that we have at least one of them.
940	VkImageUsageFlags viewRequiredFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
941	if (!(flags & viewRequiredFlags))
942		flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
943
944	return flags;
945}
946
947// Executes a combination of upload/download methods
948class UploadDownloadExecutor
949{
950public:
951	UploadDownloadExecutor(Context &context, const CaseDef& caseSpec) :
952	m_caseDef(caseSpec),
953	m_haveMaintenance2(isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance2")),
954	m_vk(context.getDeviceInterface()),
955	m_device(context.getDevice()),
956	m_queue(context.getUniversalQueue()),
957	m_queueFamilyIndex(context.getUniversalQueueFamilyIndex()),
958	m_allocator(context.getDefaultAllocator())
959	{
960	}
961
962	void run(Context& context, VkBuffer buffer);
963
964private:
965	void uploadClear(Context& context);
966	void uploadStore(Context& context);
967	void uploadCopy(Context& context);
968	void uploadDraw(Context& context);
969	void downloadCopy(Context& context, VkBuffer buffer);
970	void downloadTexture(Context& context, VkBuffer buffer);
971	void downloadLoad(Context& context, VkBuffer buffer);
972
973	void copyImageToBuffer(VkImage				image,
974						   VkBuffer				buffer,
975						   const IVec3			size,
976						   const VkAccessFlags	srcAccessMask,
977						   const VkImageLayout	oldLayout,
978						   const deUint32		numLayers);
979
980	const CaseDef&						m_caseDef;
981
982	bool								m_haveMaintenance2;
983
984	const DeviceInterface&				m_vk;
985	const VkDevice						m_device;
986	const VkQueue						m_queue;
987	const deUint32						m_queueFamilyIndex;
988	Allocator&							m_allocator;
989
990	Move<VkCommandPool>					m_cmdPool;
991	Move<VkCommandBuffer>				m_cmdBuffer;
992
993	bool								m_imageIsIntegerFormat;
994	bool								m_viewIsIntegerFormat;
995
996	// Target image for upload paths
997	Move<VkImage>						m_image;
998	MovePtr<Allocation>					m_imageAlloc;
999
1000	// Upload copy
1001	struct
1002	{
1003		Move<VkBuffer>					colorBuffer;
1004		VkDeviceSize					colorBufferSize;
1005		MovePtr<Allocation>				colorBufferAlloc;
1006	} m_uCopy;
1007
1008	// Upload draw
1009	struct
1010	{
1011		Move<VkBuffer>					vertexBuffer;
1012		MovePtr<Allocation>				vertexBufferAlloc;
1013		Move<VkPipelineLayout>			pipelineLayout;
1014		Move<VkRenderPass>				renderPass;
1015		Move<VkShaderModule>			vertexModule;
1016		Move<VkShaderModule>			fragmentModule;
1017		vector<SharedPtrVkImageView>	attachments;
1018		vector<VkImageView>				attachmentHandles;
1019		vector<SharedPtrVkPipeline>		pipelines;
1020		Move<VkFramebuffer>				framebuffer;
1021	} m_uDraw;
1022
1023	// Upload store
1024	struct
1025	{
1026		Move<VkDescriptorPool>			descriptorPool;
1027		Move<VkPipelineLayout>			pipelineLayout;
1028		Move<VkDescriptorSetLayout>		descriptorSetLayout;
1029		Move<VkDescriptorSet>			descriptorSet;
1030		VkDescriptorImageInfo			imageDescriptorInfo;
1031		Move<VkShaderModule>			computeModule;
1032		Move<VkPipeline>				computePipeline;
1033		Move<VkImageView>				imageView;
1034	} m_uStore;
1035
1036	// Download load
1037	struct
1038	{
1039		Move<VkDescriptorPool>			descriptorPool;
1040		Move<VkPipelineLayout>			pipelineLayout;
1041		Move<VkDescriptorSetLayout>		descriptorSetLayout;
1042		Move<VkDescriptorSet>			descriptorSet;
1043		Move<VkShaderModule>			computeModule;
1044		Move<VkPipeline>				computePipeline;
1045		Move<VkImageView>				inImageView;
1046		VkDescriptorImageInfo			inImageDescriptorInfo;
1047		Move<VkImage>					outImage;
1048		Move<VkImageView>				outImageView;
1049		MovePtr<Allocation>				outImageAlloc;
1050		VkDescriptorImageInfo			outImageDescriptorInfo;
1051	} m_dLoad;
1052
1053	// Download texture
1054	struct
1055	{
1056		Move<VkDescriptorPool>			descriptorPool;
1057		Move<VkPipelineLayout>			pipelineLayout;
1058		Move<VkDescriptorSetLayout>		descriptorSetLayout;
1059		Move<VkDescriptorSet>			descriptorSet;
1060		Move<VkShaderModule>			computeModule;
1061		Move<VkPipeline>				computePipeline;
1062		Move<VkImageView>				inImageView;
1063		VkDescriptorImageInfo			inImageDescriptorInfo;
1064		Move<VkSampler>					sampler;
1065		Move<VkImage>					outImage;
1066		Move<VkImageView>				outImageView;
1067		MovePtr<Allocation>				outImageAlloc;
1068		VkDescriptorImageInfo			outImageDescriptorInfo;
1069	} m_dTex;
1070
1071	VkImageLayout						m_imageLayoutAfterUpload;
1072	VkAccessFlagBits					m_imageUploadAccessMask;
1073};
1074
1075void UploadDownloadExecutor::run(Context& context, VkBuffer buffer)
1076{
1077	m_imageIsIntegerFormat	= isUintFormat(m_caseDef.imageFormat) || isIntFormat(m_caseDef.imageFormat);
1078	m_viewIsIntegerFormat	= isUintFormat(m_caseDef.viewFormat) || isIntFormat(m_caseDef.viewFormat);
1079
1080	m_cmdPool				= createCommandPool(m_vk, m_device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_queueFamilyIndex);
1081	m_cmdBuffer				= makeCommandBuffer(m_vk, m_device, *m_cmdPool);
1082	beginCommandBuffer(m_vk, *m_cmdBuffer);
1083
1084	const VkImageUsageFlags		imageUsage	= getImageUsageForTestCase(m_caseDef);
1085	const VkImageCreateFlags	imageFlags	= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | (m_haveMaintenance2 ? VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR : 0);
1086	m_image									= makeImage(m_vk, m_device, imageFlags, getImageType(m_caseDef.imageType), m_caseDef.imageFormat, m_caseDef.viewFormat,
1087														m_caseDef.isFormatListTest, m_caseDef.size, 1u, m_caseDef.numLayers, imageUsage);
1088	m_imageAlloc							= bindImage(m_vk, m_device, m_allocator, *m_image, MemoryRequirement::Any);
1089
1090	switch (m_caseDef.upload)
1091	{
1092	case UPLOAD_DRAW:
1093		uploadDraw(context);
1094		break;
1095	case UPLOAD_STORE:
1096		uploadStore(context);
1097		break;
1098	case UPLOAD_CLEAR:
1099		uploadClear(context);
1100		break;
1101	case UPLOAD_COPY:
1102		uploadCopy(context);
1103		break;
1104	default:
1105		DE_ASSERT("Unsupported upload method");
1106	}
1107
1108	switch (m_caseDef.download)
1109	{
1110	case DOWNLOAD_COPY:
1111		downloadCopy(context, buffer);
1112		break;
1113	case DOWNLOAD_LOAD:
1114		downloadLoad(context, buffer);
1115		break;
1116	case DOWNLOAD_TEXTURE:
1117		downloadTexture(context, buffer);
1118		break;
1119	default:
1120		DE_ASSERT("Unsupported download method");
1121	}
1122
1123	VK_CHECK(m_vk.endCommandBuffer(*m_cmdBuffer));
1124	submitCommandsAndWait(m_vk, m_device, m_queue, *m_cmdBuffer);
1125}
1126
1127void UploadDownloadExecutor::uploadClear(Context& context)
1128{
1129	(void) context;
1130
1131	VkImageLayout					requiredImageLayout	= VK_IMAGE_LAYOUT_GENERAL;
1132
1133	const VkImageSubresourceRange	subresourceRange	= makeColorSubresourceRange(0, m_caseDef.numLayers);
1134	const VkImageMemoryBarrier		imageInitBarrier	=
1135	{
1136		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
1137		DE_NULL,										// const void*				pNext;
1138		0u,												// VkAccessFlags			srcAccessMask;
1139		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAcessMask;
1140		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
1141		requiredImageLayout,							// VkImageLayout			newLayout;
1142		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
1143		VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
1144		*m_image,										// VkImage					image;
1145		subresourceRange								// VkImageSubresourceRange	subresourceRange;
1146	};
1147
1148	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1149		0u, DE_NULL, 0u, DE_NULL, 1u, &imageInitBarrier);
1150
1151	for (deUint32 layer = 0; layer < m_caseDef.numLayers; layer++)
1152	{
1153		const VkImageSubresourceRange	layerSubresourceRange	= makeColorSubresourceRange(layer, 1u);
1154		const deUint32					colorIdx				= layer % COLOR_TABLE_SIZE;
1155		const VkClearColorValue			clearColor				= m_imageIsIntegerFormat ? REFERENCE_CLEAR_COLOR_INT[colorIdx].color : REFERENCE_CLEAR_COLOR_FLOAT[colorIdx].color;
1156		m_vk.cmdClearColorImage(*m_cmdBuffer, *m_image, requiredImageLayout, &clearColor, 1u, &layerSubresourceRange);
1157	}
1158
1159	m_imageLayoutAfterUpload	= requiredImageLayout;
1160	m_imageUploadAccessMask		= VK_ACCESS_TRANSFER_WRITE_BIT;
1161}
1162
1163void UploadDownloadExecutor::uploadStore(Context& context)
1164{
1165	const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1166	{
1167		VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,	// VkStructureType		sType
1168		DE_NULL,											// const void*			pNext
1169		VK_IMAGE_USAGE_STORAGE_BIT,							// VkImageUsageFlags	usage;
1170	};
1171	m_uStore.imageView				= makeImageView(m_vk, m_device, *m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1172													makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1173
1174	// Setup compute pipeline
1175	m_uStore.descriptorPool			= DescriptorPoolBuilder()
1176		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1177		.build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1178
1179	m_uStore.descriptorSetLayout	= DescriptorSetLayoutBuilder()
1180		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1181		.build(m_vk, m_device);
1182
1183	m_uStore.pipelineLayout			= makePipelineLayout(m_vk, m_device, *m_uStore.descriptorSetLayout);
1184	m_uStore.descriptorSet			= makeDescriptorSet(m_vk, m_device, *m_uStore.descriptorPool, *m_uStore.descriptorSetLayout);
1185	m_uStore.imageDescriptorInfo	= makeDescriptorImageInfo(DE_NULL, *m_uStore.imageView, VK_IMAGE_LAYOUT_GENERAL);
1186	m_uStore.computeModule			= createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadStoreComp"), 0);
1187	m_uStore.computePipeline		= makeComputePipeline(m_vk, m_device, *m_uStore.pipelineLayout, *m_uStore.computeModule, DE_NULL);
1188
1189	DescriptorSetUpdateBuilder()
1190		.writeSingle(*m_uStore.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_uStore.imageDescriptorInfo)
1191		.update(m_vk, m_device);
1192
1193	// Transition storage image for shader access (imageStore)
1194	VkImageLayout requiredImageLayout	= VK_IMAGE_LAYOUT_GENERAL;
1195	const VkImageMemoryBarrier imageBarrier	=
1196	{
1197		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1198		DE_NULL,											// const void*				pNext;
1199		(VkAccessFlags)0,									// VkAccessFlags			srcAccessMask;
1200		(VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
1201		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
1202		requiredImageLayout,								// VkImageLayout			newLayout;
1203		VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1204		VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1205		*m_image,											// VkImage					image;
1206		makeColorSubresourceRange(0, m_caseDef.numLayers),	// VkImageSubresourceRange	subresourceRange;
1207	};
1208
1209	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1210		0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1211
1212	// Dispatch
1213	m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_uStore.computePipeline);
1214	m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_uStore.pipelineLayout, 0u, 1u, &m_uStore.descriptorSet.get(), 0u, DE_NULL);
1215	m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1216
1217	m_imageLayoutAfterUpload	= requiredImageLayout;
1218	m_imageUploadAccessMask		= VK_ACCESS_SHADER_WRITE_BIT;
1219}
1220
1221void UploadDownloadExecutor::uploadCopy(Context& context)
1222{
1223	(void) context;
1224
1225	// Create a host-mappable buffer with the color data to upload
1226	const VkDeviceSize	pixelSize			= tcu::getPixelSize(mapVkFormat(m_caseDef.imageFormat));
1227	const VkDeviceSize	layerSize			= m_caseDef.size.x() * m_caseDef.size.y() * m_caseDef.size.z() * pixelSize;
1228
1229	m_uCopy.colorBufferSize					= layerSize * m_caseDef.numLayers;
1230	m_uCopy.colorBuffer						= makeBuffer(m_vk, m_device, m_uCopy.colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1231	m_uCopy.colorBufferAlloc				= bindBuffer(m_vk, m_device, m_allocator, *m_uCopy.colorBuffer, MemoryRequirement::HostVisible);
1232
1233	// Fill color buffer
1234	const tcu::TextureFormat	tcuFormat	= mapVkFormat(m_caseDef.imageFormat);
1235	VkDeviceSize				layerOffset = 0ull;
1236	for (deUint32 layer = 0; layer < m_caseDef.numLayers; layer++)
1237	{
1238		tcu::PixelBufferAccess	imageAccess	= tcu::PixelBufferAccess(tcuFormat, m_caseDef.size.x(), m_caseDef.size.y(), 1u, (deUint8*) m_uCopy.colorBufferAlloc->getHostPtr() + layerOffset);
1239		const deUint32			colorIdx	= layer % COLOR_TABLE_SIZE;
1240		if (m_imageIsIntegerFormat)
1241			tcu::clear(imageAccess, COLOR_TABLE_INT[colorIdx]);
1242		else
1243			tcu::clear(imageAccess, COLOR_TABLE_FLOAT[colorIdx]);
1244		layerOffset += layerSize;
1245	}
1246
1247	flushMappedMemoryRange(m_vk, m_device, m_uCopy.colorBufferAlloc->getMemory(), m_uCopy.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1248
1249	// Prepare buffer and image for copy
1250	const VkBufferMemoryBarrier	bufferInitBarrier	=
1251	{
1252		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,			// VkStructureType    sType;
1253		DE_NULL,											// const void*        pNext;
1254		VK_ACCESS_HOST_WRITE_BIT,							// VkAccessFlags      srcAccessMask;
1255		VK_ACCESS_TRANSFER_READ_BIT,						// VkAccessFlags      dstAccessMask;
1256		VK_QUEUE_FAMILY_IGNORED,							// deUint32           srcQueueFamilyIndex;
1257		VK_QUEUE_FAMILY_IGNORED,							// deUint32           dstQueueFamilyIndex;
1258		*m_uCopy.colorBuffer,								// VkBuffer           buffer;
1259		0ull,												// VkDeviceSize       offset;
1260		VK_WHOLE_SIZE,										// VkDeviceSize       size;
1261	};
1262
1263	const VkImageMemoryBarrier	imageInitBarrier	=
1264	{
1265		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1266		DE_NULL,											// const void*				pNext;
1267		0u,													// VkAccessFlags			outputMask;
1268		VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			inputMask;
1269		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
1270		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			newLayout;
1271		VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1272		VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1273		*m_image,											// VkImage					image;
1274		makeColorSubresourceRange(0, m_caseDef.numLayers)	// VkImageSubresourceRange	subresourceRange;
1275	};
1276
1277	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1278		0u, DE_NULL, 1u, &bufferInitBarrier, 1u, &imageInitBarrier);
1279
1280	// Copy buffer to image
1281	const VkImageSubresourceLayers	subresource	=
1282	{
1283		VK_IMAGE_ASPECT_COLOR_BIT,							// VkImageAspectFlags    aspectMask;
1284		0u,													// deUint32              mipLevel;
1285		0u,													// deUint32              baseArrayLayer;
1286		m_caseDef.numLayers,								// deUint32              layerCount;
1287	};
1288
1289	const VkBufferImageCopy			region		=
1290	{
1291		0ull,												// VkDeviceSize                bufferOffset;
1292		0u,													// deUint32                    bufferRowLength;
1293		0u,													// deUint32                    bufferImageHeight;
1294		subresource,										// VkImageSubresourceLayers    imageSubresource;
1295		makeOffset3D(0, 0, 0),								// VkOffset3D                  imageOffset;
1296		makeExtent3D(m_caseDef.size),						// VkExtent3D                  imageExtent;
1297	};
1298
1299	m_vk.cmdCopyBufferToImage(*m_cmdBuffer, *m_uCopy.colorBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &region);
1300
1301	const VkImageMemoryBarrier	imagePostInitBarrier	=
1302	{
1303		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1304		DE_NULL,											// const void*				pNext;
1305		VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			outputMask;
1306		VK_ACCESS_TRANSFER_READ_BIT,						// VkAccessFlags			inputMask;
1307		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			oldLayout;
1308		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			newLayout;
1309		VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1310		VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1311		*m_image,											// VkImage					image;
1312		makeColorSubresourceRange(0, m_caseDef.numLayers)	// VkImageSubresourceRange	subresourceRange;
1313	};
1314
1315	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1316		0u, DE_NULL, 0u, DE_NULL, 1u, &imagePostInitBarrier);
1317
1318	m_imageLayoutAfterUpload	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
1319	m_imageUploadAccessMask		= VK_ACCESS_TRANSFER_WRITE_BIT;
1320}
1321
1322void UploadDownloadExecutor::uploadDraw(Context& context)
1323{
1324	// Create vertex buffer
1325	{
1326		const vector<Vec4>	vertices				= genVertexData(m_caseDef);
1327		const VkDeviceSize	vertexBufferSize		= vertices.size() * sizeof(Vec4);
1328
1329		m_uDraw.vertexBuffer						= makeBuffer(m_vk, m_device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1330		m_uDraw.vertexBufferAlloc					= bindBuffer(m_vk, m_device, m_allocator, *m_uDraw.vertexBuffer, MemoryRequirement::HostVisible);
1331		deMemcpy(m_uDraw.vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1332		flushMappedMemoryRange(m_vk, m_device, m_uDraw.vertexBufferAlloc->getMemory(), m_uDraw.vertexBufferAlloc->getOffset(), vertexBufferSize);
1333	}
1334
1335	// Create attachments and pipelines for each image layer
1336	m_uDraw.pipelineLayout							= makePipelineLayout(m_vk, m_device);
1337	m_uDraw.renderPass								= makeRenderPass(m_vk, m_device, m_caseDef.viewFormat, m_caseDef.numLayers);
1338	m_uDraw.vertexModule							= createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadDrawVert"), 0u);
1339	m_uDraw.fragmentModule							= createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadDrawFrag"), 0u);
1340
1341	for (deUint32 subpassNdx = 0; subpassNdx < m_caseDef.numLayers; ++subpassNdx)
1342	{
1343		const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1344		{
1345			VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,	// VkStructureType		sType
1346			DE_NULL,											// const void*			pNext
1347			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,				// VkImageUsageFlags	usage;
1348		};
1349		Move<VkImageView>	imageView	= makeImageView(m_vk, m_device, *m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1350														makeColorSubresourceRange(subpassNdx, 1), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1351		m_uDraw.attachmentHandles.push_back(*imageView);
1352		m_uDraw.attachments.push_back(makeSharedPtr(imageView));
1353		m_uDraw.pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(m_vk, m_device, *m_uDraw.pipelineLayout, *m_uDraw.renderPass, *m_uDraw.vertexModule, *m_uDraw.fragmentModule,
1354			m_caseDef.size.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, subpassNdx)));
1355	}
1356
1357	// Create framebuffer
1358	m_uDraw.framebuffer	= makeFramebuffer(m_vk, m_device, *m_uDraw.renderPass, static_cast<deUint32>(m_uDraw.attachmentHandles.size()), &m_uDraw.attachmentHandles[0], m_caseDef.size.swizzle(0, 1));
1359
1360	// Create command buffer
1361	{
1362		{
1363			vector<VkClearValue>	clearValues		(m_caseDef.numLayers, m_viewIsIntegerFormat ? REFERENCE_CLEAR_COLOR_INT[0] : REFERENCE_CLEAR_COLOR_FLOAT[0]);
1364
1365			const VkRect2D			renderArea	=
1366			{
1367				makeOffset2D(0, 0),
1368				makeExtent2D(m_caseDef.size.x(), m_caseDef.size.y()),
1369			};
1370
1371			const VkRenderPassBeginInfo	renderPassBeginInfo	=
1372			{
1373				VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType         sType;
1374				DE_NULL,									// const void*             pNext;
1375				*m_uDraw.renderPass,							// VkRenderPass            renderPass;
1376				*m_uDraw.framebuffer,							// VkFramebuffer           framebuffer;
1377				renderArea,									// VkRect2D                renderArea;
1378				static_cast<deUint32>(clearValues.size()),	// deUint32                clearValueCount;
1379				&clearValues[0],							// const VkClearValue*     pClearValues;
1380			};
1381
1382			m_vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1383		}
1384
1385		// Render
1386		const VkDeviceSize	vertexDataPerDraw	= 4 * 2 * sizeof(Vec4);
1387		VkDeviceSize		vertexBufferOffset	= 0ull;
1388		for (deUint32 subpassNdx = 0; subpassNdx < m_caseDef.numLayers; ++subpassNdx)
1389		{
1390			if (subpassNdx != 0)
1391				m_vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1392
1393			m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_uDraw.pipelines[subpassNdx]);
1394
1395			m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_uDraw.vertexBuffer.get(), &vertexBufferOffset);
1396			m_vk.cmdDraw(*m_cmdBuffer, 4u, 1u, 0u, 0u);
1397			vertexBufferOffset	+= vertexDataPerDraw;
1398		}
1399
1400		m_vk.cmdEndRenderPass(*m_cmdBuffer);
1401	}
1402
1403	m_imageLayoutAfterUpload	= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1404	m_imageUploadAccessMask		= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1405}
1406
1407void UploadDownloadExecutor::downloadCopy(Context& context, VkBuffer buffer)
1408{
1409	(void) context;
1410
1411	copyImageToBuffer(*m_image, buffer, m_caseDef.size, m_imageUploadAccessMask, m_imageLayoutAfterUpload, m_caseDef.numLayers);
1412}
1413
1414void UploadDownloadExecutor::downloadTexture(Context& context, VkBuffer buffer)
1415{
1416	// Create output image with download result
1417	const VkImageUsageFlags	usageFlags	= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1418	m_dTex.outImage						= makeImage(m_vk, m_device, 0u, VK_IMAGE_TYPE_2D, m_caseDef.viewFormat, m_caseDef.viewFormat, false, m_caseDef.size, 1u, m_caseDef.numLayers, usageFlags);
1419	m_dTex.outImageAlloc				= bindImage(m_vk, m_device, m_allocator, *m_dTex.outImage, MemoryRequirement::Any);
1420	m_dTex.outImageView					= makeImageView(m_vk, m_device, *m_dTex.outImage, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat, makeColorSubresourceRange(0, m_caseDef.numLayers));
1421
1422	const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1423	{
1424		VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,	// VkStructureType		sType
1425		DE_NULL,											// const void*			pNext
1426		VK_IMAGE_USAGE_SAMPLED_BIT,							// VkImageUsageFlags	usage;
1427	};
1428	m_dTex.inImageView					= makeImageView(m_vk, m_device, *m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1429														makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1430	m_dTex.sampler						= makeSampler(m_vk, m_device);
1431
1432	// Setup compute pipeline
1433	m_dTex.descriptorPool				= DescriptorPoolBuilder()
1434		.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1435		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1436		.build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1437
1438	m_dTex.descriptorSetLayout			= DescriptorSetLayoutBuilder()
1439		.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT, &m_dTex.sampler.get())
1440		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1441		.build(m_vk, m_device);
1442
1443	m_dTex.pipelineLayout				= makePipelineLayout(m_vk, m_device, *m_dTex.descriptorSetLayout);
1444	m_dTex.descriptorSet				= makeDescriptorSet(m_vk, m_device, *m_dTex.descriptorPool, *m_dTex.descriptorSetLayout);
1445	m_dTex.inImageDescriptorInfo		= makeDescriptorImageInfo(DE_NULL, *m_dTex.inImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1446	m_dTex.outImageDescriptorInfo		= makeDescriptorImageInfo(DE_NULL, *m_dTex.outImageView, VK_IMAGE_LAYOUT_GENERAL);
1447	m_dTex.computeModule				= createShaderModule(m_vk, m_device, context.getBinaryCollection().get("downloadTextureComp"), 0);
1448	m_dTex.computePipeline				= makeComputePipeline(m_vk, m_device, *m_dTex.pipelineLayout, *m_dTex.computeModule, DE_NULL);
1449
1450	DescriptorSetUpdateBuilder()
1451		.writeSingle(*m_dTex.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &m_dTex.inImageDescriptorInfo)
1452		.writeSingle(*m_dTex.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dTex.outImageDescriptorInfo)
1453		.update(m_vk, m_device);
1454
1455	// Transition images for shader access (texture / imageStore)
1456	const VkImageMemoryBarrier imageBarriers[]	=
1457	{
1458		{
1459			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1460			DE_NULL,											// const void*				pNext;
1461			(VkAccessFlags)m_imageUploadAccessMask,				// VkAccessFlags			srcAccessMask;
1462			(VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,			// VkAccessFlags			dstAccessMask;
1463			m_imageLayoutAfterUpload,							// VkImageLayout			oldLayout;
1464			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,			// VkImageLayout			newLayout;
1465			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1466			VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1467			*m_image,											// VkImage					image;
1468			makeColorSubresourceRange(0, m_caseDef.numLayers),	// VkImageSubresourceRange	subresourceRange;
1469		},
1470		{
1471			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1472			DE_NULL,											// const void*				pNext;
1473			(VkAccessFlags)0,									// VkAccessFlags			srcAccessMask;
1474			(VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
1475			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
1476			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout			newLayout;
1477			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1478			VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1479			*m_dTex.outImage,									// VkImage					image;
1480			makeColorSubresourceRange(0, m_caseDef.numLayers),	// VkImageSubresourceRange	subresourceRange;
1481		}
1482	};
1483
1484	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1485		0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1486
1487	// Dispatch
1488	m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dTex.computePipeline);
1489	m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dTex.pipelineLayout, 0u, 1u, &m_dTex.descriptorSet.get(), 0u, DE_NULL);
1490	m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1491
1492	// Copy output image to color buffer
1493	copyImageToBuffer(*m_dTex.outImage, buffer, m_caseDef.size, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, m_caseDef.numLayers);
1494}
1495
1496void UploadDownloadExecutor::downloadLoad(Context& context, VkBuffer buffer)
1497{
1498	// Create output image with download result
1499	const VkImageUsageFlags usageFlags	= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1500	m_dLoad.outImage					= makeImage(m_vk, m_device, 0u, VK_IMAGE_TYPE_2D, m_caseDef.viewFormat, m_caseDef.viewFormat, false, m_caseDef.size, 1u, m_caseDef.numLayers, usageFlags);
1501	m_dLoad.outImageAlloc				= bindImage(m_vk, m_device, m_allocator, *m_dLoad.outImage, MemoryRequirement::Any);
1502	m_dLoad.outImageView				= makeImageView(m_vk, m_device, *m_dLoad.outImage, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat, makeColorSubresourceRange(0, m_caseDef.numLayers));
1503
1504	const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1505	{
1506		VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,	// VkStructureType		sType
1507		DE_NULL,											// const void*			pNext
1508		VK_IMAGE_USAGE_STORAGE_BIT,							// VkImageUsageFlags	usage;
1509	};
1510	m_dLoad.inImageView					= makeImageView(m_vk, m_device, *m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1511														makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1512
1513	// Setup compute pipeline
1514	m_dLoad.descriptorPool				= DescriptorPoolBuilder()
1515		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u)
1516		.build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1517
1518	m_dLoad.descriptorSetLayout			= DescriptorSetLayoutBuilder()
1519		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1520		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1521		.build(m_vk, m_device);
1522
1523	m_dLoad.pipelineLayout				= makePipelineLayout(m_vk, m_device, *m_dLoad.descriptorSetLayout);
1524	m_dLoad.descriptorSet				= makeDescriptorSet(m_vk, m_device, *m_dLoad.descriptorPool, *m_dLoad.descriptorSetLayout);
1525	m_dLoad.inImageDescriptorInfo		= makeDescriptorImageInfo(DE_NULL, *m_dLoad.inImageView, VK_IMAGE_LAYOUT_GENERAL);
1526	m_dLoad.outImageDescriptorInfo		= makeDescriptorImageInfo(DE_NULL, *m_dLoad.outImageView, VK_IMAGE_LAYOUT_GENERAL);
1527	m_dLoad.computeModule				= createShaderModule(m_vk, m_device, context.getBinaryCollection().get("downloadLoadComp"), 0);
1528	m_dLoad.computePipeline				= makeComputePipeline(m_vk, m_device, *m_dLoad.pipelineLayout, *m_dLoad.computeModule, DE_NULL);
1529
1530	DescriptorSetUpdateBuilder()
1531		.writeSingle(*m_dLoad.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dLoad.inImageDescriptorInfo)
1532		.writeSingle(*m_dLoad.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dLoad.outImageDescriptorInfo)
1533		.update(m_vk, m_device);
1534
1535	// Transition storage images for shader access (imageLoad/Store)
1536	VkImageLayout requiredImageLayout = VK_IMAGE_LAYOUT_GENERAL;
1537	const VkImageMemoryBarrier imageBarriers[]	=
1538	{
1539		{
1540			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1541			DE_NULL,											// const void*				pNext;
1542			(VkAccessFlags)m_imageUploadAccessMask,				// VkAccessFlags			srcAccessMask;
1543			(VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,			// VkAccessFlags			dstAccessMask;
1544			m_imageLayoutAfterUpload,							// VkImageLayout			oldLayout;
1545			requiredImageLayout,								// VkImageLayout			newLayout;
1546			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1547			VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1548			*m_image,											// VkImage					image;
1549			makeColorSubresourceRange(0, m_caseDef.numLayers),	// VkImageSubresourceRange	subresourceRange;
1550		},
1551		{
1552			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1553			DE_NULL,											// const void*				pNext;
1554			(VkAccessFlags)0,									// VkAccessFlags			srcAccessMask;
1555			(VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
1556			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
1557			requiredImageLayout,								// VkImageLayout			newLayout;
1558			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1559			VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1560			*m_dLoad.outImage,									// VkImage					image;
1561			makeColorSubresourceRange(0, m_caseDef.numLayers),	// VkImageSubresourceRange	subresourceRange;
1562		}
1563	};
1564
1565	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1566		0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1567
1568	// Dispatch
1569	m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dLoad.computePipeline);
1570	m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dLoad.pipelineLayout, 0u, 1u, &m_dLoad.descriptorSet.get(), 0u, DE_NULL);
1571	m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1572
1573	// Copy output image to color buffer
1574	copyImageToBuffer(*m_dLoad.outImage, buffer, m_caseDef.size, VK_ACCESS_SHADER_WRITE_BIT, requiredImageLayout, m_caseDef.numLayers);
1575}
1576
1577void UploadDownloadExecutor::copyImageToBuffer(VkImage				sourceImage,
1578											   VkBuffer				buffer,
1579											   const IVec3			size,
1580											   const VkAccessFlags	srcAccessMask,
1581											   const VkImageLayout	oldLayout,
1582											   const deUint32		numLayers)
1583{
1584	// Copy result to host visible buffer for inspection
1585	const VkImageMemoryBarrier	imageBarrier	=
1586	{
1587		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
1588		DE_NULL,									// const void*				pNext;
1589		srcAccessMask,								// VkAccessFlags			outputMask;
1590		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			inputMask;
1591		oldLayout,									// VkImageLayout			oldLayout;
1592		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
1593		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
1594		VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
1595		sourceImage,								// VkImage					image;
1596		makeColorSubresourceRange(0, numLayers)		// VkImageSubresourceRange	subresourceRange;
1597	};
1598
1599	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1600		0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1601
1602	const VkImageSubresourceLayers	subresource	=
1603	{
1604		VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags    aspectMask;
1605		0u,											// deUint32              mipLevel;
1606		0u,											// deUint32              baseArrayLayer;
1607		numLayers,									// deUint32              layerCount;
1608	};
1609
1610	const VkBufferImageCopy			region		=
1611	{
1612		0ull,										// VkDeviceSize                bufferOffset;
1613		0u,											// deUint32                    bufferRowLength;
1614		0u,											// deUint32                    bufferImageHeight;
1615		subresource,								// VkImageSubresourceLayers    imageSubresource;
1616		makeOffset3D(0, 0, 0),						// VkOffset3D                  imageOffset;
1617		makeExtent3D(size),							// VkExtent3D                  imageExtent;
1618	};
1619
1620	m_vk.cmdCopyImageToBuffer(*m_cmdBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &region);
1621
1622	const VkBufferMemoryBarrier	bufferBarrier =
1623	{
1624		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
1625		DE_NULL,									// const void*        pNext;
1626		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
1627		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
1628		VK_QUEUE_FAMILY_IGNORED,					// deUint32           srcQueueFamilyIndex;
1629		VK_QUEUE_FAMILY_IGNORED,					// deUint32           dstQueueFamilyIndex;
1630		buffer,										// VkBuffer           buffer;
1631		0ull,										// VkDeviceSize       offset;
1632		VK_WHOLE_SIZE,								// VkDeviceSize       size;
1633	};
1634
1635	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1636		0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1637}
1638
1639tcu::TestStatus testMutable (Context& context, const CaseDef caseDef)
1640{
1641	const DeviceInterface&			vk			= context.getDeviceInterface();
1642	const InstanceInterface&		vki			= context.getInstanceInterface();
1643	const VkDevice					device		= context.getDevice();
1644	const VkPhysicalDevice			physDevice	= context.getPhysicalDevice();
1645	Allocator&						allocator	= context.getDefaultAllocator();
1646
1647	// If this is a VK_KHR_image_format_list test, check that the extension is supported
1648	if (caseDef.isFormatListTest && !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_image_format_list"))
1649		TCU_THROW(NotSupportedError, "VK_KHR_image_format_list not supported");
1650
1651	// Check required features on the format for the required upload/download methods
1652	VkFormatProperties	imageFormatProps, viewFormatProps;
1653	vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.imageFormat, &imageFormatProps);
1654	vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.viewFormat, &viewFormatProps);
1655
1656	VkFormatFeatureFlags	viewFormatFeatureFlags = 0u;
1657	switch (caseDef.upload)
1658	{
1659	case UPLOAD_DRAW:
1660		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
1661		break;
1662	case UPLOAD_STORE:
1663		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1664		break;
1665	default:
1666		DE_ASSERT("Invalid upload method");
1667		break;
1668	}
1669	switch (caseDef.download)
1670	{
1671	case DOWNLOAD_TEXTURE:
1672		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
1673		// For the texture case we write the samples read to a separate output image with the same view format
1674		// so we need to check that we can also use the view format for storage
1675		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1676		break;
1677	case DOWNLOAD_LOAD:
1678		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1679		break;
1680	default:
1681		DE_ASSERT("Invalid download method");
1682		break;
1683	}
1684
1685	if ((viewFormatFeatureFlags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) &&
1686		isStorageImageExtendedFormat(caseDef.viewFormat) &&
1687		!getPhysicalDeviceFeatures(vki, physDevice).shaderStorageImageExtendedFormats)
1688	{
1689		TCU_THROW(NotSupportedError, "View format requires shaderStorageImageExtended");
1690	}
1691
1692	if ((viewFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags)
1693		TCU_THROW(NotSupportedError, "View format doesn't support upload/download method");
1694
1695	// We don't use the base image for anything other than transfer
1696	// operations so there are no features to check.  However, The Vulkan
1697	// 1.0 spec does not allow us to create an image view with usage that
1698	// is not supported by the main format.  With VK_KHR_maintenance2, we
1699	// can do this via VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR.
1700	if ((imageFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags &&
1701		 !isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance2"))
1702	{
1703		TCU_THROW(NotSupportedError, "Image format doesn't support upload/download method");
1704	}
1705
1706	// Create a color buffer for host-inspection of results
1707	// For the Copy download method, this is the target of the download, for other
1708	// download methods, pixel data will be copied to this buffer from the download
1709	// target
1710	const VkDeviceSize			colorBufferSize		= caseDef.size.x() * caseDef.size.y() * caseDef.size.z() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.imageFormat));
1711	const Unique<VkBuffer>		colorBuffer			(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1712	const UniquePtr<Allocation>	colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1713	deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1714	flushMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1715
1716	// Execute the test
1717	UploadDownloadExecutor executor(context, caseDef);
1718	executor.run(context, *colorBuffer);
1719
1720	// Verify results
1721	{
1722		invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1723
1724		// For verification purposes, we use the format of the upload to generate the expected image
1725		const VkFormat						format			= caseDef.upload == UPLOAD_CLEAR || caseDef.upload == UPLOAD_COPY ? caseDef.imageFormat : caseDef.viewFormat;
1726		const tcu::TextureFormat			tcuFormat		= mapVkFormat(format);
1727		const bool							isIntegerFormat	= isUintFormat(format) || isIntFormat(format);
1728		const tcu::ConstPixelBufferAccess	resultImage		(tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers, colorBufferAlloc->getHostPtr());
1729		tcu::TextureLevel					textureLevel	(tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers);
1730		const tcu::PixelBufferAccess		expectedImage	= textureLevel.getAccess();
1731		generateExpectedImage(expectedImage, caseDef);
1732
1733		bool ok;
1734		if (isIntegerFormat)
1735			ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1736		else
1737			ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1738		return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1739	}
1740}
1741
1742tcu::TestCaseGroup* createImageMutableTests (TestContext& testCtx)
1743{
1744	de::MovePtr<TestCaseGroup> testGroup	(new TestCaseGroup(testCtx, "mutable", "Cases with mutable images"));
1745	for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1746	{
1747		const Texture&					texture					= s_textures[textureNdx];
1748		de::MovePtr<tcu::TestCaseGroup> groupByImageViewType	(new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1749
1750		for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
1751		for (int viewFormatNdx = 0; viewFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++viewFormatNdx)
1752		{
1753			if (imageFormatNdx != viewFormatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[viewFormatNdx]))
1754			{
1755				for (int upload = 0; upload < UPLOAD_LAST; upload++)
1756				for (int download = 0; download < DOWNLOAD_LAST; download++)
1757				{
1758					CaseDef caseDef =
1759					{
1760						texture.type(),
1761						texture.layerSize(),
1762						static_cast<deUint32>(texture.numLayers()),
1763						s_formats[imageFormatNdx],
1764						s_formats[viewFormatNdx],
1765						static_cast<enum Upload>(upload),
1766						static_cast<enum Download>(download),
1767						false
1768					};
1769
1770					std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[viewFormatNdx]) +
1771						"_" + getUploadString(upload) + "_" + getDownloadString(download);
1772					addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", initPrograms, testMutable, caseDef);
1773
1774					caseDef.isFormatListTest = true;
1775					caseName += "_format_list";
1776					addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", initPrograms, testMutable, caseDef);
1777				}
1778			}
1779		}
1780
1781		testGroup->addChild(groupByImageViewType.release());
1782	}
1783
1784	return testGroup.release();
1785}
1786
1787} // image
1788} // vkt
1789