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