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 #include "vktCustomInstancesDevices.hpp"
29 
30 #include "vkBuilderUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vkRef.hpp"
36 #include "vkDefs.hpp"
37 #include "vkPlatform.hpp"
38 #include "vkWsiUtil.hpp"
39 #include "vkDeviceUtil.hpp"
40 
41 #include "deUniquePtr.hpp"
42 #include "deSharedPtr.hpp"
43 
44 #include "tcuImageCompare.hpp"
45 #include "tcuTestLog.hpp"
46 #include "tcuTextureUtil.hpp"
47 #include "tcuPlatform.hpp"
48 #include "tcuCommandLine.hpp"
49 
50 #include <string>
51 #include <vector>
52 
53 using namespace vk;
54 using namespace tcu;
55 using namespace vk::wsi;
56 
57 using de::UniquePtr;
58 using de::MovePtr;
59 using de::SharedPtr;
60 using std::vector;
61 using std::string;
62 
63 namespace vkt
64 {
65 namespace image
66 {
67 
68 typedef SharedPtr<Unique<VkPipeline> >	SharedPtrVkPipeline;
69 typedef SharedPtr<Unique<VkImageView> >	SharedPtrVkImageView;
70 
71 template<typename T>
makeSharedPtr(Move<T> move)72 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
73 {
74 	return SharedPtr<Unique<T> >(new Unique<T>(move));
75 }
76 
77 enum Upload {
78 	UPLOAD_CLEAR = 0,
79 	UPLOAD_COPY,
80 	UPLOAD_STORE,
81 	UPLOAD_DRAW,
82 	UPLOAD_LAST
83 };
84 
85 enum Download {
86 	DOWNLOAD_COPY = 0,
87 	DOWNLOAD_LOAD,
88 	DOWNLOAD_TEXTURE,
89 	DOWNLOAD_LAST
90 };
91 
getUploadString(const int upload)92 std::string getUploadString (const int upload)
93 {
94 	const char* strs[] = { "clear", "copy", "store", "draw" };
95 	return strs[upload];
96 }
97 
getDownloadString(const int download)98 std::string getDownloadString (const int download)
99 {
100 	const char* strs[] = { "copy", "load", "texture" };
101 	return strs[download];
102 }
103 
104 struct CaseDef
105 {
106 	ImageType		imageType;
107 	IVec3			size;
108 	deUint32		numLayers;
109 	VkFormat		imageFormat;
110 	VkFormat		viewFormat;
111 	enum Upload		upload;
112 	enum Download	download;
113 	bool			isFormatListTest;
114 	bool			isSwapchainImageTest;
115 	Type			wsiType;
116 };
117 
118 static const deUint32 COLOR_TABLE_SIZE = 4;
119 
120 // Reference color values for float color rendering. Values have been chosen
121 // so that when the bit patterns are reinterpreted as a 16-bit float, we do not
122 // run into NaN / inf / denorm values.
123 static const Vec4	COLOR_TABLE_FLOAT[COLOR_TABLE_SIZE]	=
124 {
125 	Vec4(0.00f, 0.40f, 0.80f, 0.10f),
126 	Vec4(0.50f, 0.10f, 0.90f, 0.20f),
127 	Vec4(0.20f, 0.60f, 1.00f, 0.30f),
128 	Vec4(0.30f, 0.70f, 0.00f, 0.40f),
129 };
130 
131 // Reference color values for integer color rendering. We avoid negative
132 // values (even for SINT formats) to avoid the situation where sign extension
133 // leads to NaN / inf values when they are reinterpreted with a float
134 // format.
135 static const IVec4	COLOR_TABLE_INT[COLOR_TABLE_SIZE]	=
136 {
137 	IVec4(0x70707070, 0x3C3C3C3C, 0x65656565, 0x29292929),
138 	IVec4(0x3C3C3C3C, 0x65656565, 0x29292929, 0x70707070),
139 	IVec4(0x29292929, 0x70707070, 0x3C3C3C3C, 0x65656565),
140 	IVec4(0x65656565, 0x29292929, 0x70707070, 0x3C3C3C3C),
141 };
142 
143 // Reference clear colors created from the color table values
144 static const VkClearValue REFERENCE_CLEAR_COLOR_FLOAT[COLOR_TABLE_SIZE]	=
145 {
146 	makeClearValueColorF32(COLOR_TABLE_FLOAT[0].x(), COLOR_TABLE_FLOAT[0].y(), COLOR_TABLE_FLOAT[0].z(), COLOR_TABLE_FLOAT[0].w()),
147 	makeClearValueColorF32(COLOR_TABLE_FLOAT[1].x(), COLOR_TABLE_FLOAT[1].y(), COLOR_TABLE_FLOAT[1].z(), COLOR_TABLE_FLOAT[1].w()),
148 	makeClearValueColorF32(COLOR_TABLE_FLOAT[2].x(), COLOR_TABLE_FLOAT[2].y(), COLOR_TABLE_FLOAT[2].z(), COLOR_TABLE_FLOAT[2].w()),
149 	makeClearValueColorF32(COLOR_TABLE_FLOAT[3].x(), COLOR_TABLE_FLOAT[3].y(), COLOR_TABLE_FLOAT[3].z(), COLOR_TABLE_FLOAT[3].w()),
150 };
151 
152 static const Texture s_textures[] =
153 {
154 	Texture(IMAGE_TYPE_2D,			tcu::IVec3(32, 32, 1),	1),
155 	Texture(IMAGE_TYPE_2D_ARRAY,	tcu::IVec3(32, 32, 1),	4),
156 };
157 
getClearValueInt(const CaseDef & caseDef,deUint32 colorTableIndex)158 static VkClearValue getClearValueInt(const CaseDef& caseDef, deUint32 colorTableIndex)
159 {
160 	VkClearValue		clearValue;
161 	deUint32			channelMask	= 0;
162 
163 	if (caseDef.upload == UPLOAD_DRAW)
164 	{
165 		// We use this mask to get small color values in the vertex buffer and
166 		// avoid possible round off errors from int-to-float conversions.
167 		channelMask = 0xFFu;
168 	}
169 	else
170 	{
171 		VkFormat			format;
172 		tcu::TextureFormat	tcuFormat;
173 
174 		// Select a mask such that no integer-based color values end up
175 		// reinterpreted as NaN/Inf/denorm values.
176 		if (caseDef.upload == UPLOAD_CLEAR || caseDef.upload == UPLOAD_COPY)
177 			format = caseDef.imageFormat;
178 		else
179 			format = caseDef.viewFormat;
180 
181 		tcuFormat = mapVkFormat(format);
182 
183 		switch (getChannelSize(tcuFormat.type))
184 		{
185 			case 1: // 8-bit
186 				channelMask = 0xFFu;
187 				break;
188 			case 2: // 16-bit
189 				channelMask = 0xFFFFu;
190 				break;
191 			case 4: // 32-bit
192 				channelMask = 0xFFFFFFFFu;
193 				break;
194 			default:
195 				DE_ASSERT(0);
196 		}
197 	}
198 
199 	clearValue.color.int32[0] = COLOR_TABLE_INT[colorTableIndex].x() & channelMask;
200 	clearValue.color.int32[1] = COLOR_TABLE_INT[colorTableIndex].y() & channelMask;
201 	clearValue.color.int32[2] = COLOR_TABLE_INT[colorTableIndex].z() & channelMask;
202 	clearValue.color.int32[3] = COLOR_TABLE_INT[colorTableIndex].w() & channelMask;
203 
204 	return clearValue;
205 }
206 
getImageType(const ImageType textureImageType)207 VkImageType getImageType (const ImageType textureImageType)
208 {
209 	switch (textureImageType)
210 	{
211 		case IMAGE_TYPE_2D:
212 		case IMAGE_TYPE_2D_ARRAY:
213 			return VK_IMAGE_TYPE_2D;
214 
215 		default:
216 			DE_ASSERT(0);
217 			return VK_IMAGE_TYPE_LAST;
218 	}
219 }
220 
getImageViewType(const ImageType textureImageType)221 VkImageViewType getImageViewType (const ImageType textureImageType)
222 {
223 	switch (textureImageType)
224 	{
225 		case IMAGE_TYPE_2D:
226 			return VK_IMAGE_VIEW_TYPE_2D;
227 		case IMAGE_TYPE_2D_ARRAY:
228 			return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
229 
230 		default:
231 			DE_ASSERT(0);
232 			return VK_IMAGE_VIEW_TYPE_LAST;
233 	}
234 }
235 
236 static const VkFormat s_formats[] =
237 {
238 	VK_FORMAT_R32G32B32A32_SFLOAT,
239 	VK_FORMAT_R16G16B16A16_SFLOAT,
240 	VK_FORMAT_R32G32_SFLOAT,
241 	VK_FORMAT_R16G16_SFLOAT,
242 	VK_FORMAT_R32_SFLOAT,
243 
244 	VK_FORMAT_R32G32B32A32_UINT,
245 	VK_FORMAT_R16G16B16A16_UINT,
246 	VK_FORMAT_R8G8B8A8_UINT,
247 	VK_FORMAT_R32G32_UINT,
248 	VK_FORMAT_R16G16_UINT,
249 	VK_FORMAT_R32_UINT,
250 
251 	VK_FORMAT_R32G32B32A32_SINT,
252 	VK_FORMAT_R16G16B16A16_SINT,
253 	VK_FORMAT_R8G8B8A8_SINT,
254 	VK_FORMAT_R32G32_SINT,
255 	VK_FORMAT_R16G16_SINT,
256 	VK_FORMAT_R32_SINT,
257 
258 	VK_FORMAT_R8G8B8A8_UNORM,
259 	VK_FORMAT_R8G8B8A8_SNORM,
260 	VK_FORMAT_R8G8B8A8_SRGB,
261 	VK_FORMAT_B8G8R8A8_UNORM,
262 	VK_FORMAT_B8G8R8A8_SNORM,
263 	VK_FORMAT_B8G8R8A8_SRGB,
264 };
265 
266 static const VkFormat s_swapchainFormats[] =
267 {
268 	VK_FORMAT_R8G8B8A8_UNORM,
269 	VK_FORMAT_R8G8B8A8_SNORM,
270 	VK_FORMAT_R8G8B8A8_SRGB,
271 	VK_FORMAT_B8G8R8A8_UNORM,
272 	VK_FORMAT_B8G8R8A8_SNORM,
273 	VK_FORMAT_B8G8R8A8_SRGB,
274 };
275 
isSRGBConversionRequired(const CaseDef & caseDef)276 bool isSRGBConversionRequired(const CaseDef& caseDef)
277 {
278 	bool required = false;
279 
280 	if (isSRGB(mapVkFormat(caseDef.imageFormat)))
281 	{
282 		if (caseDef.upload == UPLOAD_CLEAR)
283 		{
284 			required = true;
285 		}
286 	}
287 
288 	if (isSRGB(mapVkFormat(caseDef.viewFormat)))
289 	{
290 		if (caseDef.upload == UPLOAD_DRAW || caseDef.upload == UPLOAD_STORE)
291 		{
292 			required = true;
293 		}
294 	}
295 
296 	return required;
297 }
298 
299 
formatsAreCompatible(const VkFormat format0,const VkFormat format1)300 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
301 {
302 	return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
303 }
304 
getColorFormatStr(const int numComponents,const bool isUint,const bool isSint)305 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
306 {
307 	std::ostringstream str;
308 	if (numComponents == 1)
309 		str << (isUint ? "uint" : isSint ? "int" : "float");
310 	else
311 		str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
312 
313 	return str.str();
314 }
315 
getShaderSamplerType(const tcu::TextureFormat & format,VkImageViewType type)316 std::string getShaderSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
317 {
318 	std::ostringstream samplerType;
319 
320 	if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
321 		samplerType << "u";
322 	else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
323 		samplerType << "i";
324 
325 	switch (type)
326 	{
327 		case VK_IMAGE_VIEW_TYPE_2D:
328 			samplerType << "sampler2D";
329 			break;
330 
331 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
332 			samplerType << "sampler2DArray";
333 			break;
334 
335 		default:
336 			DE_FATAL("Ivalid image view type");
337 			break;
338 	}
339 
340 	return samplerType.str();
341 }
342 
initPrograms(SourceCollections & programCollection,const CaseDef caseDef)343 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
344 {
345 	if (caseDef.upload == UPLOAD_DRAW)
346 	{
347 		{
348 			std::ostringstream src;
349 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
350 				<< "\n"
351 				<< "layout(location = 0) in  vec4 in_position;\n"
352 				<< "layout(location = 1) in  vec4 in_color;\n"
353 				<< "layout(location = 0) out vec4 out_color;\n"
354 				<< "\n"
355 				<< "out gl_PerVertex {\n"
356 				<< "	vec4 gl_Position;\n"
357 				<< "};\n"
358 				<< "\n"
359 				<< "void main(void)\n"
360 				<< "{\n"
361 				<< "	gl_Position	= in_position;\n"
362 				<< "	out_color	= in_color;\n"
363 				<< "}\n";
364 
365 			programCollection.glslSources.add("uploadDrawVert") << glu::VertexSource(src.str());
366 		}
367 
368 		{
369 			const int	numComponents		= getNumUsedChannels(mapVkFormat(caseDef.viewFormat).order);
370 			const bool	isUint				= isUintFormat(caseDef.viewFormat);
371 			const bool	isSint				= isIntFormat(caseDef.viewFormat);
372 			const std::string colorFormat	= getColorFormatStr(numComponents, isUint, isSint);
373 
374 			std::ostringstream src;
375 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
376 				<< "\n"
377 				<< "layout(location = 0) in  vec4 in_color;\n"
378 				<< "layout(location = 0) out " << colorFormat << " out_color;\n"
379 				<< "\n"
380 				<< "void main(void)\n"
381 				<< "{\n"
382 				<< "    out_color = " << colorFormat << "("
383 				<< (numComponents == 1 ? "in_color.r"   :
384 					numComponents == 2 ? "in_color.rg"  :
385 					numComponents == 3 ? "in_color.rgb" : "in_color")
386 				<< ");\n"
387 				<< "}\n";
388 
389 			programCollection.glslSources.add("uploadDrawFrag") << glu::FragmentSource(src.str());
390 		}
391 	}
392 
393 	if (caseDef.upload == UPLOAD_STORE)
394 	{
395 		const TextureFormat	tcuFormat		= mapVkFormat(caseDef.viewFormat);
396 		const std::string	imageFormatStr	= getShaderImageFormatQualifier(tcuFormat);
397 		const std::string	imageTypeStr	= getShaderImageType(tcuFormat, caseDef.imageType);
398 		const std::string	colorTypeStr	= isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
399 		const bool			isIntegerFormat	= isUintFormat(caseDef.viewFormat) || isIntFormat(caseDef.viewFormat);
400 
401 		std::ostringstream src;
402 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
403 			<< "\n"
404 			<< "layout (local_size_x = 1) in;\n"
405 			<< "\n"
406 			<< "layout(binding=0, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " u_image;\n"
407 			<< "\n"
408 			<< "const " << colorTypeStr << " colorTable[] = " << colorTypeStr << "[](\n";
409 		for (deUint32 idx = 0; idx < COLOR_TABLE_SIZE; idx++)
410 		{
411 			if (isIntegerFormat)
412 			{
413 				const VkClearValue	clearValue	= getClearValueInt(caseDef, idx);
414 
415 				src << "     " << colorTypeStr << "(" << clearValue.color.int32[0] << ", " << clearValue.color.int32[1] << ", " << clearValue.color.int32[2] << ", " << clearValue.color.int32[3] << ")";
416 			}
417 			else
418 				src << "     " << colorTypeStr << "(" << COLOR_TABLE_FLOAT[idx].x() << ", " << COLOR_TABLE_FLOAT[idx].y() << ", " << COLOR_TABLE_FLOAT[idx].z() << ", " << COLOR_TABLE_FLOAT[idx].w() << ")";
419 			if (idx < COLOR_TABLE_SIZE - 1)
420 				src << ",";
421 			src << "\n";
422 		}
423 		src << ");\n"
424 			<< "\n"
425 			<< "void main(void)\n"
426 			<< "{\n";
427 		if (caseDef.imageType == IMAGE_TYPE_2D)
428 		{
429 			src	<< "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
430 		}
431 		else
432 		{
433 			DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
434 			src	<< "    ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
435 		}
436 		src << "    " << colorTypeStr << " color = colorTable[gl_GlobalInvocationID.z];\n"
437 			<< "    imageStore(u_image, pos, color);\n"
438 			<< "}\n";
439 
440 		programCollection.glslSources.add("uploadStoreComp") << glu::ComputeSource(src.str());
441 	}
442 
443 	if (caseDef.download == DOWNLOAD_LOAD)
444 	{
445 		const TextureFormat	tcuFormat		= mapVkFormat(caseDef.viewFormat);
446 		const std::string	imageFormatStr	= getShaderImageFormatQualifier(tcuFormat);
447 		const std::string	imageTypeStr	= getShaderImageType(tcuFormat, caseDef.imageType);
448 		const std::string	colorTypeStr	= isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
449 
450 		std::ostringstream src;
451 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
452 			<< "\n"
453 			<< "layout (local_size_x = 1) in;\n"
454 			<< "\n"
455 			<< "layout(binding=0, " << imageFormatStr << ") readonly uniform " << imageTypeStr << " in_image;\n"
456 			<< "layout(binding=1, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " out_image;\n"
457 			<< "\n"
458 			<< "void main(void)\n"
459 			<< "{\n";
460 		if (caseDef.imageType == IMAGE_TYPE_2D)
461 		{
462 			src	<< "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
463 		}
464 		else
465 		{
466 			DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
467 			src	<< "    ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
468 		}
469 		src	<< "    imageStore(out_image, pos, imageLoad(in_image, pos));\n"
470 			<< "}\n";
471 
472 		programCollection.glslSources.add("downloadLoadComp") << glu::ComputeSource(src.str());
473 	}
474 
475 	if (caseDef.download == DOWNLOAD_TEXTURE)
476 	{
477 		const TextureFormat		tcuFormat		= mapVkFormat(caseDef.viewFormat);
478 		const VkImageViewType	viewType		= getImageViewType(caseDef.imageType);
479 		const std::string		samplerTypeStr	= getShaderSamplerType(tcuFormat, viewType);
480 		const std::string		imageFormatStr	= getShaderImageFormatQualifier(tcuFormat);
481 		const std::string		imageTypeStr	= getShaderImageType(tcuFormat, caseDef.imageType);
482 		const std::string		colorTypeStr	= isUintFormat(caseDef.viewFormat) ? "uvec4" : isIntFormat(caseDef.viewFormat) ? "ivec4" : "vec4";
483 
484 		std::ostringstream src;
485 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
486 			<< "\n"
487 			<< "layout (local_size_x = 1) in;\n"
488 			<< "\n"
489 			<< "layout(binding=0) uniform " << samplerTypeStr << " u_tex;\n"
490 			<< "layout(binding=1, " << imageFormatStr << ") writeonly uniform " << imageTypeStr << " out_image;\n"
491 			<< "\n"
492 			<< "void main(void)\n"
493 			<< "{\n";
494 		if (caseDef.imageType == IMAGE_TYPE_2D)
495 		{
496 			src	<< "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
497 		}
498 		else
499 		{
500 			DE_ASSERT(caseDef.imageType == IMAGE_TYPE_2D_ARRAY);
501 			src	<< "    ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);\n";
502 		}
503 		src	<< "    imageStore(out_image, pos, texelFetch(u_tex, pos, 0));\n"
504 			<< "}\n";
505 
506 		programCollection.glslSources.add("downloadTextureComp") << glu::ComputeSource(src.str());
507 	}
508 }
509 
makeImage(const DeviceInterface & vk,const VkDevice device,VkImageCreateFlags flags,VkImageType imageType,const VkFormat format,const VkFormat viewFormat,const bool useImageFormatList,const IVec3 & size,const deUint32 numMipLevels,const deUint32 numLayers,const VkImageUsageFlags usage)510 Move<VkImage> makeImage (const DeviceInterface&		vk,
511 						 const VkDevice				device,
512 						 VkImageCreateFlags			flags,
513 						 VkImageType				imageType,
514 						 const VkFormat				format,
515 						 const VkFormat				viewFormat,
516 						 const bool					useImageFormatList,
517 						 const IVec3&				size,
518 						 const deUint32				numMipLevels,
519 						 const deUint32				numLayers,
520 						 const VkImageUsageFlags	usage)
521 {
522 	const VkFormat formatList[2] =
523 	{
524 		format,
525 		viewFormat
526 	};
527 
528 	const VkImageFormatListCreateInfo formatListInfo =
529 	{
530 		VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR,	// VkStructureType			sType;
531 		DE_NULL,												// const void*				pNext;
532 		2u,														// deUint32					viewFormatCount
533 		formatList												// const VkFormat*			pViewFormats
534 	};
535 
536 	const VkImageCreateInfo imageParams =
537 	{
538 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,					// VkStructureType			sType;
539 		useImageFormatList ? &formatListInfo : DE_NULL,			// const void*				pNext;
540 		flags,													// VkImageCreateFlags		flags;
541 		imageType,												// VkImageType				imageType;
542 		format,													// VkFormat					format;
543 		makeExtent3D(size),										// VkExtent3D				extent;
544 		numMipLevels,											// deUint32					mipLevels;
545 		numLayers,												// deUint32					arrayLayers;
546 		VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits	samples;
547 		VK_IMAGE_TILING_OPTIMAL,								// VkImageTiling			tiling;
548 		usage,													// VkImageUsageFlags		usage;
549 		VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode			sharingMode;
550 		0u,														// deUint32					queueFamilyIndexCount;
551 		DE_NULL,												// const deUint32*			pQueueFamilyIndices;
552 		VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout			initialLayout;
553 	};
554 	return createImage(vk, device, &imageParams);
555 }
556 
makeColorSubresourceRange(const int baseArrayLayer,const int layerCount)557 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
558 {
559 	return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
560 }
561 
makeSampler(const DeviceInterface & vk,const VkDevice device)562 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
563 {
564 	const VkSamplerCreateInfo samplerParams =
565 	{
566 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType			sType;
567 		DE_NULL,									// const void*				pNext;
568 		(VkSamplerCreateFlags)0,					// VkSamplerCreateFlags		flags;
569 		VK_FILTER_NEAREST,							// VkFilter					magFilter;
570 		VK_FILTER_NEAREST,							// VkFilter					minFilter;
571 		VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode		mipmapMode;
572 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeU;
573 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeV;
574 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeW;
575 		0.0f,										// float					mipLodBias;
576 		VK_FALSE,									// VkBool32					anisotropyEnable;
577 		1.0f,										// float					maxAnisotropy;
578 		VK_FALSE,									// VkBool32					compareEnable;
579 		VK_COMPARE_OP_ALWAYS,						// VkCompareOp				compareOp;
580 		0.0f,										// float					minLod;
581 		0.0f,										// float					maxLod;
582 		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// VkBorderColor			borderColor;
583 		VK_FALSE,									// VkBool32					unnormalizedCoordinates;
584 	};
585 
586 	return createSampler(vk, device, &samplerParams);
587 }
588 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const IVec2 & renderSize,const VkPrimitiveTopology topology,const deUint32 subpass)589 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
590 									   const VkDevice				device,
591 									   const VkPipelineLayout		pipelineLayout,
592 									   const VkRenderPass			renderPass,
593 									   const VkShaderModule			vertexModule,
594 									   const VkShaderModule			fragmentModule,
595 									   const IVec2&					renderSize,
596 									   const VkPrimitiveTopology	topology,
597 									   const deUint32				subpass)
598 {
599 	const std::vector<VkViewport>			viewports							(1, makeViewport(renderSize));
600 	const std::vector<VkRect2D>				scissors							(1, makeRect2D(renderSize));
601 
602 	const VkVertexInputBindingDescription	vertexInputBindingDescription		=
603 	{
604 		0u,									// deUint32				binding;
605 		(deUint32)(2 * sizeof(Vec4)),		// deUint32				stride;
606 		VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate	inputRate;
607 	};
608 
609 	const VkVertexInputAttributeDescription	vertexInputAttributeDescriptions[]	=
610 	{
611 		{
612 			0u,								// deUint32			location;
613 			0u,								// deUint32			binding;
614 			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat			format;
615 			0u,								// deUint32			offset;
616 		},
617 		{
618 			1u,								// deUint32			location;
619 			0u,								// deUint32			binding;
620 			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat			format;
621 			(deUint32)sizeof(Vec4),			// deUint32			offset;
622 		}
623 	};
624 
625 	const VkPipelineVertexInputStateCreateInfo	vertexInputStateCreateInfo	=
626 	{
627 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType                             sType;
628 		DE_NULL,													// const void*                                 pNext;
629 		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags       flags;
630 		1u,															// deUint32                                    vertexBindingDescriptionCount;
631 		&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
632 		2u,															// deUint32                                    vertexAttributeDescriptionCount;
633 		vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
634 	};
635 
636 	return vk::makeGraphicsPipeline(vk,									// const DeviceInterface&                        vk
637 									device,								// const VkDevice                                device
638 									pipelineLayout,						// const VkPipelineLayout                        pipelineLayout
639 									vertexModule,						// const VkShaderModule                          vertexShaderModule
640 									DE_NULL,							// const VkShaderModule                          tessellationControlModule
641 									DE_NULL,							// const VkShaderModule                          tessellationEvalModule
642 									DE_NULL,							// const VkShaderModule                          geometryShaderModule
643 									fragmentModule,						// const VkShaderModule                          fragmentShaderModule
644 									renderPass,							// const VkRenderPass                            renderPass
645 									viewports,							// const std::vector<VkViewport>&                viewports
646 									scissors,							// const std::vector<VkRect2D>&                  scissors
647 									topology,							// const VkPrimitiveTopology                     topology
648 									subpass,							// const deUint32                                subpass
649 									0u,									// const deUint32                                patchControlPoints
650 									&vertexInputStateCreateInfo);		// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
651 }
652 
makeComputePipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkShaderModule shaderModule,const VkSpecializationInfo * specInfo)653 Move<VkPipeline> makeComputePipeline (const DeviceInterface&		vk,
654 									  const VkDevice				device,
655 									  const VkPipelineLayout		pipelineLayout,
656 									  const VkShaderModule			shaderModule,
657 									  const VkSpecializationInfo*	specInfo)
658 {
659 	const VkPipelineShaderStageCreateInfo shaderStageInfo =
660 	{
661 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType					sType;
662 		DE_NULL,												// const void*						pNext;
663 		(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags	flags;
664 		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits			stage;
665 		shaderModule,											// VkShaderModule					module;
666 		"main",													// const char*						pName;
667 		specInfo,												// const VkSpecializationInfo*		pSpecializationInfo;
668 	};
669 	const VkComputePipelineCreateInfo pipelineInfo =
670 	{
671 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,			// VkStructureType					sType;
672 		DE_NULL,												// const void*						pNext;
673 		(VkPipelineCreateFlags)0,								// VkPipelineCreateFlags			flags;
674 		shaderStageInfo,										// VkPipelineShaderStageCreateInfo	stage;
675 		pipelineLayout,											// VkPipelineLayout					layout;
676 		DE_NULL,												// VkPipeline						basePipelineHandle;
677 		0,														// deInt32							basePipelineIndex;
678 	};
679 	return createComputePipeline(vk, device, DE_NULL , &pipelineInfo);
680 }
681 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const deUint32 numLayers)682 Move<VkRenderPass> makeRenderPass (const DeviceInterface&	vk,
683 								   const VkDevice			device,
684 								   const VkFormat			colorFormat,
685 								   const deUint32			numLayers)
686 {
687 	const VkAttachmentDescription colorAttachmentDescription =
688 	{
689 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
690 		colorFormat,										// VkFormat							format;
691 		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
692 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
693 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
694 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
695 		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
696 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout					initialLayout;
697 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
698 	};
699 	vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
700 
701 	// Create a subpass for each attachment (each attachement is a layer of an arrayed image).
702 	vector<VkAttachmentReference>	colorAttachmentReferences	(numLayers);
703 	vector<VkSubpassDescription>	subpasses;
704 
705 	// Ordering here must match the framebuffer attachments
706 	for (deUint32 i = 0; i < numLayers; ++i)
707 	{
708 		const VkAttachmentReference attachmentRef =
709 		{
710 			i,													// deUint32			attachment;
711 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
712 		};
713 
714 		colorAttachmentReferences[i]	= attachmentRef;
715 
716 		const VkSubpassDescription		subpassDescription	=
717 		{
718 			(VkSubpassDescriptionFlags)0,					// VkSubpassDescriptionFlags		flags;
719 			VK_PIPELINE_BIND_POINT_GRAPHICS,				// VkPipelineBindPoint				pipelineBindPoint;
720 			0u,												// deUint32							inputAttachmentCount;
721 			DE_NULL,										// const VkAttachmentReference*		pInputAttachments;
722 			1u,												// deUint32							colorAttachmentCount;
723 			&colorAttachmentReferences[i],					// const VkAttachmentReference*		pColorAttachments;
724 			DE_NULL,										// const VkAttachmentReference*		pResolveAttachments;
725 			DE_NULL,										// const VkAttachmentReference*		pDepthStencilAttachment;
726 			0u,												// deUint32							preserveAttachmentCount;
727 			DE_NULL											// const deUint32*					pPreserveAttachments;
728 		};
729 		subpasses.push_back(subpassDescription);
730 	}
731 
732 	const VkRenderPassCreateInfo renderPassInfo =
733 	{
734 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,				// VkStructureType					sType;
735 		DE_NULL,												// const void*						pNext;
736 		(VkRenderPassCreateFlags)0,								// VkRenderPassCreateFlags			flags;
737 		static_cast<deUint32>(attachmentDescriptions.size()),	// deUint32							attachmentCount;
738 		&attachmentDescriptions[0],								// const VkAttachmentDescription*	pAttachments;
739 		static_cast<deUint32>(subpasses.size()),				// deUint32							subpassCount;
740 		&subpasses[0],											// const VkSubpassDescription*		pSubpasses;
741 		0u,														// deUint32							dependencyCount;
742 		DE_NULL													// const VkSubpassDependency*		pDependencies;
743 	};
744 
745 	return createRenderPass(vk, device, &renderPassInfo);
746 }
747 
makeCommandBuffer(const DeviceInterface & vk,const VkDevice device,const VkCommandPool commandPool)748 Move<VkCommandBuffer> makeCommandBuffer	(const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
749 {
750 	return allocateCommandBuffer(vk, device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
751 }
752 
genVertexData(const CaseDef & caseDef)753 vector<Vec4> genVertexData (const CaseDef& caseDef)
754 {
755 	vector<Vec4>	vectorData;
756 	const bool		isIntegerFormat	= isUintFormat(caseDef.viewFormat) || isIntFormat(caseDef.viewFormat);
757 
758 	for (deUint32 z = 0; z < caseDef.numLayers; z++)
759 	{
760 		const deUint32	colorIdx	= z % COLOR_TABLE_SIZE;
761 		Vec4			color;
762 
763 		if (isIntegerFormat)
764 		{
765 			const VkClearValue	clearValue	= getClearValueInt(caseDef, colorIdx);
766 			const IVec4			colorInt	(clearValue.color.int32[0], clearValue.color.int32[1], clearValue.color.int32[2], clearValue.color.int32[3]);
767 
768 			color = colorInt.cast<float>();
769 		}
770 		else
771 		{
772 			color = COLOR_TABLE_FLOAT[colorIdx];
773 		}
774 
775 		vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
776 		vectorData.push_back(color);
777 		vectorData.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
778 		vectorData.push_back(color);
779 		vectorData.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
780 		vectorData.push_back(color);
781 		vectorData.push_back(Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
782 		vectorData.push_back(color);
783 	}
784 
785 	return vectorData;
786 }
787 
generateExpectedImage(const tcu::PixelBufferAccess & image,const CaseDef & caseDef)788 void generateExpectedImage(const tcu::PixelBufferAccess& image, const CaseDef& caseDef)
789 {
790 	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(image.getFormat().type);
791 	const bool						isIntegerFormat	= channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
792 	const IVec2						size			= caseDef.size.swizzle(0, 1);
793 
794 	for (int z = 0; z < static_cast<int>(caseDef.numLayers); z++)
795 	{
796 		const deUint32	colorIdx	= z % COLOR_TABLE_SIZE;
797 		for (int y = 0; y < size.y(); y++)
798 		for (int x = 0; x < size.x(); x++)
799 		{
800 			if (isIntegerFormat)
801 			{
802 				const VkClearValue	clearValue	= getClearValueInt(caseDef, colorIdx);
803 				const IVec4			colorInt	(clearValue.color.int32[0], clearValue.color.int32[1], clearValue.color.int32[2], clearValue.color.int32[3]);
804 
805 				image.setPixel(colorInt, x, y, z);
806 			}
807 			else
808 				if(isSRGBConversionRequired(caseDef))
809 					image.setPixel(tcu::linearToSRGB(COLOR_TABLE_FLOAT[colorIdx]), x, y, z);
810 				else
811 					image.setPixel(COLOR_TABLE_FLOAT[colorIdx], x, y, z);
812 		}
813 	}
814 }
815 
getImageUsageForTestCase(const CaseDef & caseDef)816 VkImageUsageFlags getImageUsageForTestCase (const CaseDef& caseDef)
817 {
818 	VkImageUsageFlags flags = 0u;
819 
820 	switch (caseDef.upload)
821 	{
822 	case UPLOAD_CLEAR:
823 		flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
824 		break;
825 	case UPLOAD_DRAW:
826 		flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
827 		break;
828 	case UPLOAD_STORE:
829 		flags |= VK_IMAGE_USAGE_STORAGE_BIT;
830 		break;
831 	case UPLOAD_COPY:
832 		flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
833 		break;
834 	default:
835 		DE_FATAL("Invalid upload method");
836 		break;
837 	}
838 
839 	switch (caseDef.download)
840 	{
841 	case DOWNLOAD_TEXTURE:
842 		flags |= VK_IMAGE_USAGE_SAMPLED_BIT;
843 		break;
844 	case DOWNLOAD_LOAD:
845 		flags |= VK_IMAGE_USAGE_STORAGE_BIT;
846 		break;
847 	case DOWNLOAD_COPY:
848 		flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
849 		break;
850 	default:
851 		DE_FATAL("Invalid download method");
852 		break;
853 	}
854 
855 	// We can only create a view for the image if it is going to be used for any of these usages,
856 	// so let's make sure that we have at least one of them.
857 	VkImageUsageFlags viewRequiredFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
858 	if (!(flags & viewRequiredFlags))
859 		flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
860 
861 	return flags;
862 }
863 
864 // Executes a combination of upload/download methods
865 class UploadDownloadExecutor
866 {
867 public:
UploadDownloadExecutor(Context & context,VkDevice device,VkQueue queue,deUint32 queueFamilyIndex,const CaseDef & caseSpec)868 	UploadDownloadExecutor(Context& context, VkDevice device, VkQueue queue, deUint32 queueFamilyIndex, const CaseDef& caseSpec) :
869 	m_caseDef(caseSpec),
870 	m_haveMaintenance2(context.isDeviceFunctionalitySupported("VK_KHR_maintenance2")),
871 	m_vk(context.getDeviceInterface()),
872 	m_device(device),
873 	m_queue(queue),
874 	m_queueFamilyIndex(queueFamilyIndex),
875 	m_allocator(context.getDeviceInterface(), device,
876 		    getPhysicalDeviceMemoryProperties(context.getInstanceInterface(),
877 						      context.getPhysicalDevice()))
878 	{
879 	}
880 
881 	void runSwapchain(Context& context, VkBuffer buffer, VkImage image);
882 
883 	void run(Context& context, VkBuffer buffer);
884 
885 private:
886 	void uploadClear(Context& context);
887 	void uploadStore(Context& context);
888 	void uploadCopy(Context& context);
889 	void uploadDraw(Context& context);
890 	void downloadCopy(Context& context, VkBuffer buffer);
891 	void downloadTexture(Context& context, VkBuffer buffer);
892 	void downloadLoad(Context& context, VkBuffer buffer);
893 
894 	void copyImageToBuffer(VkImage				image,
895 						   VkBuffer				buffer,
896 						   const IVec3			size,
897 						   const VkAccessFlags	srcAccessMask,
898 						   const VkImageLayout	oldLayout,
899 						   const deUint32		numLayers);
900 
901 	const CaseDef&						m_caseDef;
902 
903 	bool								m_haveMaintenance2;
904 
905 	const DeviceInterface&				m_vk;
906 	const VkDevice						m_device;
907 	const VkQueue						m_queue;
908 	const deUint32						m_queueFamilyIndex;
909 	SimpleAllocator						m_allocator;
910 
911 	Move<VkCommandPool>					m_cmdPool;
912 	Move<VkCommandBuffer>				m_cmdBuffer;
913 
914 	bool								m_imageIsIntegerFormat;
915 	bool								m_viewIsIntegerFormat;
916 
917 	// Target image for upload paths
918 	VkImage								m_image;
919 	Move<VkImage>						m_imageHolder;
920 	MovePtr<Allocation>					m_imageAlloc;
921 
922 	// Upload copy
923 	struct
924 	{
925 		Move<VkBuffer>					colorBuffer;
926 		VkDeviceSize					colorBufferSize;
927 		MovePtr<Allocation>				colorBufferAlloc;
928 	} m_uCopy;
929 
930 	// Upload draw
931 	struct
932 	{
933 		Move<VkBuffer>					vertexBuffer;
934 		MovePtr<Allocation>				vertexBufferAlloc;
935 		Move<VkPipelineLayout>			pipelineLayout;
936 		Move<VkRenderPass>				renderPass;
937 		Move<VkShaderModule>			vertexModule;
938 		Move<VkShaderModule>			fragmentModule;
939 		vector<SharedPtrVkImageView>	attachments;
940 		vector<VkImageView>				attachmentHandles;
941 		vector<SharedPtrVkPipeline>		pipelines;
942 		Move<VkFramebuffer>				framebuffer;
943 	} m_uDraw;
944 
945 	// Upload store
946 	struct
947 	{
948 		Move<VkDescriptorPool>			descriptorPool;
949 		Move<VkPipelineLayout>			pipelineLayout;
950 		Move<VkDescriptorSetLayout>		descriptorSetLayout;
951 		Move<VkDescriptorSet>			descriptorSet;
952 		VkDescriptorImageInfo			imageDescriptorInfo;
953 		Move<VkShaderModule>			computeModule;
954 		Move<VkPipeline>				computePipeline;
955 		Move<VkImageView>				imageView;
956 	} m_uStore;
957 
958 	// Download load
959 	struct
960 	{
961 		Move<VkDescriptorPool>			descriptorPool;
962 		Move<VkPipelineLayout>			pipelineLayout;
963 		Move<VkDescriptorSetLayout>		descriptorSetLayout;
964 		Move<VkDescriptorSet>			descriptorSet;
965 		Move<VkShaderModule>			computeModule;
966 		Move<VkPipeline>				computePipeline;
967 		Move<VkImageView>				inImageView;
968 		VkDescriptorImageInfo			inImageDescriptorInfo;
969 		Move<VkImage>					outImage;
970 		Move<VkImageView>				outImageView;
971 		MovePtr<Allocation>				outImageAlloc;
972 		VkDescriptorImageInfo			outImageDescriptorInfo;
973 	} m_dLoad;
974 
975 	// Download texture
976 	struct
977 	{
978 		Move<VkDescriptorPool>			descriptorPool;
979 		Move<VkPipelineLayout>			pipelineLayout;
980 		Move<VkDescriptorSetLayout>		descriptorSetLayout;
981 		Move<VkDescriptorSet>			descriptorSet;
982 		Move<VkShaderModule>			computeModule;
983 		Move<VkPipeline>				computePipeline;
984 		Move<VkImageView>				inImageView;
985 		VkDescriptorImageInfo			inImageDescriptorInfo;
986 		Move<VkSampler>					sampler;
987 		Move<VkImage>					outImage;
988 		Move<VkImageView>				outImageView;
989 		MovePtr<Allocation>				outImageAlloc;
990 		VkDescriptorImageInfo			outImageDescriptorInfo;
991 	} m_dTex;
992 
993 	VkImageLayout						m_imageLayoutAfterUpload;
994 	VkAccessFlagBits					m_imageUploadAccessMask;
995 };
996 
997 
runSwapchain(Context & context,VkBuffer buffer,VkImage image)998 void UploadDownloadExecutor::runSwapchain(Context& context, VkBuffer buffer, VkImage image)
999 {
1000 	m_imageIsIntegerFormat = isUintFormat(m_caseDef.imageFormat) || isIntFormat(m_caseDef.imageFormat);
1001 	m_viewIsIntegerFormat = isUintFormat(m_caseDef.viewFormat) || isIntFormat(m_caseDef.viewFormat);
1002 
1003 	m_cmdPool = createCommandPool(m_vk, m_device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_queueFamilyIndex);
1004 	m_cmdBuffer = makeCommandBuffer(m_vk, m_device, *m_cmdPool);
1005 	beginCommandBuffer(m_vk, *m_cmdBuffer);
1006 
1007 	m_image = image;
1008 
1009 	switch (m_caseDef.upload)
1010 	{
1011 	case UPLOAD_DRAW:
1012 		uploadDraw(context);
1013 		break;
1014 	case UPLOAD_STORE:
1015 		uploadStore(context);
1016 		break;
1017 	case UPLOAD_CLEAR:
1018 		uploadClear(context);
1019 		break;
1020 	case UPLOAD_COPY:
1021 		uploadCopy(context);
1022 		break;
1023 	default:
1024 		DE_FATAL("Unsupported upload method");
1025 	}
1026 
1027 	switch (m_caseDef.download)
1028 	{
1029 	case DOWNLOAD_COPY:
1030 		downloadCopy(context, buffer);
1031 		break;
1032 	case DOWNLOAD_LOAD:
1033 		downloadLoad(context, buffer);
1034 		break;
1035 	case DOWNLOAD_TEXTURE:
1036 		downloadTexture(context, buffer);
1037 		break;
1038 	default:
1039 		DE_FATAL("Unsupported download method");
1040 	}
1041 
1042 	endCommandBuffer(m_vk, *m_cmdBuffer);
1043 	submitCommandsAndWait(m_vk, m_device, m_queue, *m_cmdBuffer);
1044 
1045 }
1046 
run(Context & context,VkBuffer buffer)1047 void UploadDownloadExecutor::run(Context& context, VkBuffer buffer)
1048 {
1049 	m_imageIsIntegerFormat	= isUintFormat(m_caseDef.imageFormat) || isIntFormat(m_caseDef.imageFormat);
1050 	m_viewIsIntegerFormat	= isUintFormat(m_caseDef.viewFormat) || isIntFormat(m_caseDef.viewFormat);
1051 
1052 	m_cmdPool				= createCommandPool(m_vk, m_device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_queueFamilyIndex);
1053 	m_cmdBuffer				= makeCommandBuffer(m_vk, m_device, *m_cmdPool);
1054 	beginCommandBuffer(m_vk, *m_cmdBuffer);
1055 
1056 	const VkImageUsageFlags		imageUsage	= getImageUsageForTestCase(m_caseDef);
1057 	const VkImageCreateFlags	imageFlags	= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | (m_haveMaintenance2 ? VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR : 0);
1058 
1059 	m_imageHolder							= makeImage(m_vk, m_device, imageFlags, getImageType(m_caseDef.imageType), m_caseDef.imageFormat, m_caseDef.viewFormat,
1060 														m_caseDef.isFormatListTest, m_caseDef.size, 1u, m_caseDef.numLayers, imageUsage);
1061 	m_image									= *m_imageHolder;
1062 	m_imageAlloc							= bindImage(m_vk, m_device, m_allocator, m_image, MemoryRequirement::Any);
1063 
1064 	switch (m_caseDef.upload)
1065 	{
1066 	case UPLOAD_DRAW:
1067 		uploadDraw(context);
1068 		break;
1069 	case UPLOAD_STORE:
1070 		uploadStore(context);
1071 		break;
1072 	case UPLOAD_CLEAR:
1073 		uploadClear(context);
1074 		break;
1075 	case UPLOAD_COPY:
1076 		uploadCopy(context);
1077 		break;
1078 	default:
1079 		DE_FATAL("Unsupported upload method");
1080 	}
1081 
1082 	switch (m_caseDef.download)
1083 	{
1084 	case DOWNLOAD_COPY:
1085 		downloadCopy(context, buffer);
1086 		break;
1087 	case DOWNLOAD_LOAD:
1088 		downloadLoad(context, buffer);
1089 		break;
1090 	case DOWNLOAD_TEXTURE:
1091 		downloadTexture(context, buffer);
1092 		break;
1093 	default:
1094 		DE_FATAL("Unsupported download method");
1095 	}
1096 
1097 	endCommandBuffer(m_vk, *m_cmdBuffer);
1098 	submitCommandsAndWait(m_vk, m_device, m_queue, *m_cmdBuffer);
1099 }
1100 
uploadClear(Context & context)1101 void UploadDownloadExecutor::uploadClear(Context& context)
1102 {
1103 	(void) context;
1104 
1105 	VkImageLayout					requiredImageLayout	= VK_IMAGE_LAYOUT_GENERAL;
1106 
1107 	const VkImageSubresourceRange	subresourceRange	= makeColorSubresourceRange(0, m_caseDef.numLayers);
1108 	const VkImageMemoryBarrier		imageInitBarrier	=
1109 	{
1110 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
1111 		DE_NULL,										// const void*				pNext;
1112 		0u,												// VkAccessFlags			srcAccessMask;
1113 		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAcessMask;
1114 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
1115 		requiredImageLayout,							// VkImageLayout			newLayout;
1116 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
1117 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
1118 		m_image,										// VkImage					image;
1119 		subresourceRange								// VkImageSubresourceRange	subresourceRange;
1120 	};
1121 
1122 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1123 		0u, DE_NULL, 0u, DE_NULL, 1u, &imageInitBarrier);
1124 
1125 	for (deUint32 layer = 0; layer < m_caseDef.numLayers; layer++)
1126 	{
1127 		const VkImageSubresourceRange	layerSubresourceRange	= makeColorSubresourceRange(layer, 1u);
1128 		const deUint32					colorIdx				= layer % COLOR_TABLE_SIZE;
1129 		const VkClearColorValue			clearColor				= m_imageIsIntegerFormat ? getClearValueInt(m_caseDef, colorIdx).color : REFERENCE_CLEAR_COLOR_FLOAT[colorIdx].color;
1130 		m_vk.cmdClearColorImage(*m_cmdBuffer, m_image, requiredImageLayout, &clearColor, 1u, &layerSubresourceRange);
1131 	}
1132 
1133 	m_imageLayoutAfterUpload	= requiredImageLayout;
1134 	m_imageUploadAccessMask		= VK_ACCESS_TRANSFER_WRITE_BIT;
1135 }
1136 
uploadStore(Context & context)1137 void UploadDownloadExecutor::uploadStore(Context& context)
1138 {
1139 	const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1140 	{
1141 		VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,	// VkStructureType		sType
1142 		DE_NULL,											// const void*			pNext
1143 		VK_IMAGE_USAGE_STORAGE_BIT,							// VkImageUsageFlags	usage;
1144 	};
1145 	m_uStore.imageView				= makeImageView(m_vk, m_device, m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1146 													makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1147 
1148 	// Setup compute pipeline
1149 	m_uStore.descriptorPool			= DescriptorPoolBuilder()
1150 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1151 		.build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1152 
1153 	m_uStore.descriptorSetLayout	= DescriptorSetLayoutBuilder()
1154 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1155 		.build(m_vk, m_device);
1156 
1157 	m_uStore.pipelineLayout			= makePipelineLayout(m_vk, m_device, *m_uStore.descriptorSetLayout);
1158 	m_uStore.descriptorSet			= makeDescriptorSet(m_vk, m_device, *m_uStore.descriptorPool, *m_uStore.descriptorSetLayout);
1159 	m_uStore.imageDescriptorInfo	= makeDescriptorImageInfo(DE_NULL, *m_uStore.imageView, VK_IMAGE_LAYOUT_GENERAL);
1160 	m_uStore.computeModule			= createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadStoreComp"), 0);
1161 	m_uStore.computePipeline		= makeComputePipeline(m_vk, m_device, *m_uStore.pipelineLayout, *m_uStore.computeModule, DE_NULL);
1162 
1163 	DescriptorSetUpdateBuilder()
1164 		.writeSingle(*m_uStore.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_uStore.imageDescriptorInfo)
1165 		.update(m_vk, m_device);
1166 
1167 	// Transition storage image for shader access (imageStore)
1168 	VkImageLayout requiredImageLayout	= VK_IMAGE_LAYOUT_GENERAL;
1169 	const VkImageMemoryBarrier imageBarrier	=
1170 	{
1171 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1172 		DE_NULL,											// const void*				pNext;
1173 		(VkAccessFlags)0,									// VkAccessFlags			srcAccessMask;
1174 		(VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
1175 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
1176 		requiredImageLayout,								// VkImageLayout			newLayout;
1177 		VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1178 		VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1179 		m_image,											// VkImage					image;
1180 		makeColorSubresourceRange(0, m_caseDef.numLayers),	// VkImageSubresourceRange	subresourceRange;
1181 	};
1182 
1183 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1184 		0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1185 
1186 	// Dispatch
1187 	m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_uStore.computePipeline);
1188 	m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_uStore.pipelineLayout, 0u, 1u, &m_uStore.descriptorSet.get(), 0u, DE_NULL);
1189 	m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1190 
1191 	m_imageLayoutAfterUpload	= requiredImageLayout;
1192 	m_imageUploadAccessMask		= VK_ACCESS_SHADER_WRITE_BIT;
1193 }
1194 
uploadCopy(Context & context)1195 void UploadDownloadExecutor::uploadCopy(Context& context)
1196 {
1197 	(void) context;
1198 
1199 	// Create a host-mappable buffer with the color data to upload
1200 	const VkDeviceSize	pixelSize			= tcu::getPixelSize(mapVkFormat(m_caseDef.imageFormat));
1201 	const VkDeviceSize	layerSize			= m_caseDef.size.x() * m_caseDef.size.y() * m_caseDef.size.z() * pixelSize;
1202 
1203 	m_uCopy.colorBufferSize					= layerSize * m_caseDef.numLayers;
1204 	m_uCopy.colorBuffer						= makeBuffer(m_vk, m_device, m_uCopy.colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1205 	m_uCopy.colorBufferAlloc				= bindBuffer(m_vk, m_device, m_allocator, *m_uCopy.colorBuffer, MemoryRequirement::HostVisible);
1206 
1207 	// Fill color buffer
1208 	const tcu::TextureFormat	tcuFormat	= mapVkFormat(m_caseDef.imageFormat);
1209 	VkDeviceSize				layerOffset = 0ull;
1210 	for (deUint32 layer = 0; layer < m_caseDef.numLayers; layer++)
1211 	{
1212 		tcu::PixelBufferAccess	imageAccess	= tcu::PixelBufferAccess(tcuFormat, m_caseDef.size.x(), m_caseDef.size.y(), 1u, (deUint8*) m_uCopy.colorBufferAlloc->getHostPtr() + layerOffset);
1213 		const deUint32			colorIdx	= layer % COLOR_TABLE_SIZE;
1214 		if (m_imageIsIntegerFormat)
1215 		{
1216 			const VkClearValue	clearValue	= getClearValueInt(m_caseDef, colorIdx);
1217 			const IVec4			colorInt	(clearValue.color.int32[0], clearValue.color.int32[1], clearValue.color.int32[2], clearValue.color.int32[3]);
1218 
1219 			tcu::clear(imageAccess, colorInt);
1220 		}
1221 		else
1222 			tcu::clear(imageAccess, COLOR_TABLE_FLOAT[colorIdx]);
1223 		layerOffset += layerSize;
1224 	}
1225 
1226 	flushAlloc(m_vk, m_device, *(m_uCopy.colorBufferAlloc));
1227 
1228 	// Prepare buffer and image for copy
1229 	const VkBufferMemoryBarrier	bufferInitBarrier	=
1230 	{
1231 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,			// VkStructureType    sType;
1232 		DE_NULL,											// const void*        pNext;
1233 		VK_ACCESS_HOST_WRITE_BIT,							// VkAccessFlags      srcAccessMask;
1234 		VK_ACCESS_TRANSFER_READ_BIT,						// VkAccessFlags      dstAccessMask;
1235 		VK_QUEUE_FAMILY_IGNORED,							// deUint32           srcQueueFamilyIndex;
1236 		VK_QUEUE_FAMILY_IGNORED,							// deUint32           dstQueueFamilyIndex;
1237 		*m_uCopy.colorBuffer,								// VkBuffer           buffer;
1238 		0ull,												// VkDeviceSize       offset;
1239 		VK_WHOLE_SIZE,										// VkDeviceSize       size;
1240 	};
1241 
1242 	const VkImageMemoryBarrier	imageInitBarrier	=
1243 	{
1244 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1245 		DE_NULL,											// const void*				pNext;
1246 		0u,													// VkAccessFlags			srcAccessMask;
1247 		VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			dstAccessMask;
1248 		VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
1249 		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			newLayout;
1250 		VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1251 		VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1252 		m_image,											// VkImage					image;
1253 		makeColorSubresourceRange(0, m_caseDef.numLayers)	// VkImageSubresourceRange	subresourceRange;
1254 	};
1255 
1256 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1257 		0u, DE_NULL, 1u, &bufferInitBarrier, 1u, &imageInitBarrier);
1258 
1259 	// Copy buffer to image
1260 	const VkImageSubresourceLayers	subresource	=
1261 	{
1262 		VK_IMAGE_ASPECT_COLOR_BIT,							// VkImageAspectFlags    aspectMask;
1263 		0u,													// deUint32              mipLevel;
1264 		0u,													// deUint32              baseArrayLayer;
1265 		m_caseDef.numLayers,								// deUint32              layerCount;
1266 	};
1267 
1268 	const VkBufferImageCopy			region		=
1269 	{
1270 		0ull,												// VkDeviceSize                bufferOffset;
1271 		0u,													// deUint32                    bufferRowLength;
1272 		0u,													// deUint32                    bufferImageHeight;
1273 		subresource,										// VkImageSubresourceLayers    imageSubresource;
1274 		makeOffset3D(0, 0, 0),								// VkOffset3D                  imageOffset;
1275 		makeExtent3D(m_caseDef.size),						// VkExtent3D                  imageExtent;
1276 	};
1277 
1278 	m_vk.cmdCopyBufferToImage(*m_cmdBuffer, *m_uCopy.colorBuffer, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &region);
1279 
1280 	const VkImageMemoryBarrier	imagePostInitBarrier	=
1281 	{
1282 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1283 		DE_NULL,											// const void*				pNext;
1284 		VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			srcAccessMask;
1285 		VK_ACCESS_TRANSFER_READ_BIT,						// VkAccessFlags			dstAccessMask;
1286 		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			oldLayout;
1287 		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			newLayout;
1288 		VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1289 		VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1290 		m_image,											// VkImage					image;
1291 		makeColorSubresourceRange(0, m_caseDef.numLayers)	// VkImageSubresourceRange	subresourceRange;
1292 	};
1293 
1294 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1295 		0u, DE_NULL, 0u, DE_NULL, 1u, &imagePostInitBarrier);
1296 
1297 	m_imageLayoutAfterUpload	= VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
1298 	m_imageUploadAccessMask		= VK_ACCESS_TRANSFER_WRITE_BIT;
1299 }
1300 
uploadDraw(Context & context)1301 void UploadDownloadExecutor::uploadDraw(Context& context)
1302 {
1303 	// Create vertex buffer
1304 	{
1305 		const vector<Vec4>	vertices				= genVertexData(m_caseDef);
1306 		const VkDeviceSize	vertexBufferSize		= vertices.size() * sizeof(Vec4);
1307 
1308 		m_uDraw.vertexBuffer						= makeBuffer(m_vk, m_device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1309 		m_uDraw.vertexBufferAlloc					= bindBuffer(m_vk, m_device, m_allocator, *m_uDraw.vertexBuffer, MemoryRequirement::HostVisible);
1310 		deMemcpy(m_uDraw.vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1311 		flushAlloc(m_vk, m_device, *(m_uDraw.vertexBufferAlloc));
1312 	}
1313 
1314 	// Create attachments and pipelines for each image layer
1315 	m_uDraw.pipelineLayout							= makePipelineLayout(m_vk, m_device);
1316 	m_uDraw.renderPass								= makeRenderPass(m_vk, m_device, m_caseDef.viewFormat, m_caseDef.numLayers);
1317 	m_uDraw.vertexModule							= createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadDrawVert"), 0u);
1318 	m_uDraw.fragmentModule							= createShaderModule(m_vk, m_device, context.getBinaryCollection().get("uploadDrawFrag"), 0u);
1319 
1320 	for (deUint32 subpassNdx = 0; subpassNdx < m_caseDef.numLayers; ++subpassNdx)
1321 	{
1322 		const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1323 		{
1324 			VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,	// VkStructureType		sType
1325 			DE_NULL,											// const void*			pNext
1326 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,				// VkImageUsageFlags	usage;
1327 		};
1328 		Move<VkImageView>	imageView	= makeImageView(m_vk, m_device, m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1329 														makeColorSubresourceRange(subpassNdx, 1), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1330 		m_uDraw.attachmentHandles.push_back(*imageView);
1331 		m_uDraw.attachments.push_back(makeSharedPtr(imageView));
1332 		m_uDraw.pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(m_vk, m_device, *m_uDraw.pipelineLayout, *m_uDraw.renderPass, *m_uDraw.vertexModule, *m_uDraw.fragmentModule,
1333 			m_caseDef.size.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, subpassNdx)));
1334 	}
1335 
1336 	// Create framebuffer
1337 	{
1338 		const IVec2 size = m_caseDef.size.swizzle(0, 1);
1339 
1340 		m_uDraw.framebuffer = makeFramebuffer(m_vk, m_device, *m_uDraw.renderPass, static_cast<deUint32>(m_uDraw.attachmentHandles.size()), &m_uDraw.attachmentHandles[0], static_cast<deUint32>(size.x()), static_cast<deUint32>(size.y()));
1341 	}
1342 
1343 	// Create command buffer
1344 	{
1345 		{
1346 			vector<VkClearValue>	clearValues		(m_caseDef.numLayers, m_viewIsIntegerFormat ? getClearValueInt(m_caseDef, 0) : REFERENCE_CLEAR_COLOR_FLOAT[0]);
1347 
1348 			beginRenderPass(m_vk, *m_cmdBuffer, *m_uDraw.renderPass, *m_uDraw.framebuffer, makeRect2D(0, 0, m_caseDef.size.x(), m_caseDef.size.y()), (deUint32)clearValues.size(), &clearValues[0]);
1349 		}
1350 
1351 		// Render
1352 		const VkDeviceSize	vertexDataPerDraw	= 4 * 2 * sizeof(Vec4);
1353 		VkDeviceSize		vertexBufferOffset	= 0ull;
1354 		for (deUint32 subpassNdx = 0; subpassNdx < m_caseDef.numLayers; ++subpassNdx)
1355 		{
1356 			if (subpassNdx != 0)
1357 				m_vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1358 
1359 			m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_uDraw.pipelines[subpassNdx]);
1360 
1361 			m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_uDraw.vertexBuffer.get(), &vertexBufferOffset);
1362 			m_vk.cmdDraw(*m_cmdBuffer, 4u, 1u, 0u, 0u);
1363 			vertexBufferOffset	+= vertexDataPerDraw;
1364 		}
1365 
1366 		endRenderPass(m_vk, *m_cmdBuffer);
1367 	}
1368 
1369 	m_imageLayoutAfterUpload	= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1370 	m_imageUploadAccessMask		= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1371 }
1372 
downloadCopy(Context & context,VkBuffer buffer)1373 void UploadDownloadExecutor::downloadCopy(Context& context, VkBuffer buffer)
1374 {
1375 	(void) context;
1376 
1377 	copyImageToBuffer(m_image, buffer, m_caseDef.size, m_imageUploadAccessMask, m_imageLayoutAfterUpload, m_caseDef.numLayers);
1378 }
1379 
downloadTexture(Context & context,VkBuffer buffer)1380 void UploadDownloadExecutor::downloadTexture(Context& context, VkBuffer buffer)
1381 {
1382 	// Create output image with download result
1383 	const VkImageUsageFlags	usageFlags	= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1384 	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);
1385 	m_dTex.outImageAlloc				= bindImage(m_vk, m_device, m_allocator, *m_dTex.outImage, MemoryRequirement::Any);
1386 	m_dTex.outImageView					= makeImageView(m_vk, m_device, *m_dTex.outImage, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat, makeColorSubresourceRange(0, m_caseDef.numLayers));
1387 
1388 	const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1389 	{
1390 		VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,	// VkStructureType		sType
1391 		DE_NULL,											// const void*			pNext
1392 		VK_IMAGE_USAGE_SAMPLED_BIT,							// VkImageUsageFlags	usage;
1393 	};
1394 	m_dTex.inImageView					= makeImageView(m_vk, m_device, m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1395 														makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1396 	m_dTex.sampler						= makeSampler(m_vk, m_device);
1397 
1398 	// Setup compute pipeline
1399 	m_dTex.descriptorPool				= DescriptorPoolBuilder()
1400 		.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1401 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1402 		.build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1403 
1404 	m_dTex.descriptorSetLayout			= DescriptorSetLayoutBuilder()
1405 		.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT, &m_dTex.sampler.get())
1406 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1407 		.build(m_vk, m_device);
1408 
1409 	m_dTex.pipelineLayout				= makePipelineLayout(m_vk, m_device, *m_dTex.descriptorSetLayout);
1410 	m_dTex.descriptorSet				= makeDescriptorSet(m_vk, m_device, *m_dTex.descriptorPool, *m_dTex.descriptorSetLayout);
1411 	m_dTex.inImageDescriptorInfo		= makeDescriptorImageInfo(DE_NULL, *m_dTex.inImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1412 	m_dTex.outImageDescriptorInfo		= makeDescriptorImageInfo(DE_NULL, *m_dTex.outImageView, VK_IMAGE_LAYOUT_GENERAL);
1413 	m_dTex.computeModule				= createShaderModule(m_vk, m_device, context.getBinaryCollection().get("downloadTextureComp"), 0);
1414 	m_dTex.computePipeline				= makeComputePipeline(m_vk, m_device, *m_dTex.pipelineLayout, *m_dTex.computeModule, DE_NULL);
1415 
1416 	DescriptorSetUpdateBuilder()
1417 		.writeSingle(*m_dTex.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &m_dTex.inImageDescriptorInfo)
1418 		.writeSingle(*m_dTex.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dTex.outImageDescriptorInfo)
1419 		.update(m_vk, m_device);
1420 
1421 	// Transition images for shader access (texture / imageStore)
1422 	const VkImageMemoryBarrier imageBarriers[]	=
1423 	{
1424 		{
1425 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1426 			DE_NULL,											// const void*				pNext;
1427 			(VkAccessFlags)m_imageUploadAccessMask,				// VkAccessFlags			srcAccessMask;
1428 			(VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,			// VkAccessFlags			dstAccessMask;
1429 			m_imageLayoutAfterUpload,							// VkImageLayout			oldLayout;
1430 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,			// VkImageLayout			newLayout;
1431 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1432 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1433 			m_image,											// VkImage					image;
1434 			makeColorSubresourceRange(0, m_caseDef.numLayers),	// VkImageSubresourceRange	subresourceRange;
1435 		},
1436 		{
1437 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1438 			DE_NULL,											// const void*				pNext;
1439 			(VkAccessFlags)0,									// VkAccessFlags			srcAccessMask;
1440 			(VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
1441 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
1442 			VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout			newLayout;
1443 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1444 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1445 			*m_dTex.outImage,									// VkImage					image;
1446 			makeColorSubresourceRange(0, m_caseDef.numLayers),	// VkImageSubresourceRange	subresourceRange;
1447 		}
1448 	};
1449 
1450 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1451 		0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1452 
1453 	// Dispatch
1454 	m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dTex.computePipeline);
1455 	m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dTex.pipelineLayout, 0u, 1u, &m_dTex.descriptorSet.get(), 0u, DE_NULL);
1456 	m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1457 
1458 	// Copy output image to color buffer
1459 	copyImageToBuffer(*m_dTex.outImage, buffer, m_caseDef.size, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, m_caseDef.numLayers);
1460 }
1461 
downloadLoad(Context & context,VkBuffer buffer)1462 void UploadDownloadExecutor::downloadLoad(Context& context, VkBuffer buffer)
1463 {
1464 	// Create output image with download result
1465 	const VkImageUsageFlags usageFlags	= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1466 	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);
1467 	m_dLoad.outImageAlloc				= bindImage(m_vk, m_device, m_allocator, *m_dLoad.outImage, MemoryRequirement::Any);
1468 	m_dLoad.outImageView				= makeImageView(m_vk, m_device, *m_dLoad.outImage, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat, makeColorSubresourceRange(0, m_caseDef.numLayers));
1469 
1470 	const vk::VkImageViewUsageCreateInfo viewUsageCreateInfo =
1471 	{
1472 		VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR,	// VkStructureType		sType
1473 		DE_NULL,											// const void*			pNext
1474 		VK_IMAGE_USAGE_STORAGE_BIT,							// VkImageUsageFlags	usage;
1475 	};
1476 	m_dLoad.inImageView					= makeImageView(m_vk, m_device, m_image, getImageViewType(m_caseDef.imageType), m_caseDef.viewFormat,
1477 														makeColorSubresourceRange(0, m_caseDef.numLayers), m_haveMaintenance2 ? &viewUsageCreateInfo : DE_NULL);
1478 
1479 	// Setup compute pipeline
1480 	m_dLoad.descriptorPool				= DescriptorPoolBuilder()
1481 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u)
1482 		.build(m_vk, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1483 
1484 	m_dLoad.descriptorSetLayout			= DescriptorSetLayoutBuilder()
1485 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1486 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1487 		.build(m_vk, m_device);
1488 
1489 	m_dLoad.pipelineLayout				= makePipelineLayout(m_vk, m_device, *m_dLoad.descriptorSetLayout);
1490 	m_dLoad.descriptorSet				= makeDescriptorSet(m_vk, m_device, *m_dLoad.descriptorPool, *m_dLoad.descriptorSetLayout);
1491 	m_dLoad.inImageDescriptorInfo		= makeDescriptorImageInfo(DE_NULL, *m_dLoad.inImageView, VK_IMAGE_LAYOUT_GENERAL);
1492 	m_dLoad.outImageDescriptorInfo		= makeDescriptorImageInfo(DE_NULL, *m_dLoad.outImageView, VK_IMAGE_LAYOUT_GENERAL);
1493 	m_dLoad.computeModule				= createShaderModule(m_vk, m_device, context.getBinaryCollection().get("downloadLoadComp"), 0);
1494 	m_dLoad.computePipeline				= makeComputePipeline(m_vk, m_device, *m_dLoad.pipelineLayout, *m_dLoad.computeModule, DE_NULL);
1495 
1496 	DescriptorSetUpdateBuilder()
1497 		.writeSingle(*m_dLoad.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dLoad.inImageDescriptorInfo)
1498 		.writeSingle(*m_dLoad.descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &m_dLoad.outImageDescriptorInfo)
1499 		.update(m_vk, m_device);
1500 
1501 	// Transition storage images for shader access (imageLoad/Store)
1502 	VkImageLayout requiredImageLayout = VK_IMAGE_LAYOUT_GENERAL;
1503 	const VkImageMemoryBarrier imageBarriers[]	=
1504 	{
1505 		{
1506 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1507 			DE_NULL,											// const void*				pNext;
1508 			(VkAccessFlags)m_imageUploadAccessMask,				// VkAccessFlags			srcAccessMask;
1509 			(VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,			// VkAccessFlags			dstAccessMask;
1510 			m_imageLayoutAfterUpload,							// VkImageLayout			oldLayout;
1511 			requiredImageLayout,								// VkImageLayout			newLayout;
1512 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1513 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1514 			m_image,											// VkImage					image;
1515 			makeColorSubresourceRange(0, m_caseDef.numLayers),	// VkImageSubresourceRange	subresourceRange;
1516 		},
1517 		{
1518 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1519 			DE_NULL,											// const void*				pNext;
1520 			(VkAccessFlags)0,									// VkAccessFlags			srcAccessMask;
1521 			(VkAccessFlags)VK_ACCESS_SHADER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
1522 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
1523 			requiredImageLayout,								// VkImageLayout			newLayout;
1524 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1525 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
1526 			*m_dLoad.outImage,									// VkImage					image;
1527 			makeColorSubresourceRange(0, m_caseDef.numLayers),	// VkImageSubresourceRange	subresourceRange;
1528 		}
1529 	};
1530 
1531 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1532 		0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1533 
1534 	// Dispatch
1535 	m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dLoad.computePipeline);
1536 	m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_dLoad.pipelineLayout, 0u, 1u, &m_dLoad.descriptorSet.get(), 0u, DE_NULL);
1537 	m_vk.cmdDispatch(*m_cmdBuffer, m_caseDef.size.x(), m_caseDef.size.y(), m_caseDef.numLayers);
1538 
1539 	// Copy output image to color buffer
1540 	copyImageToBuffer(*m_dLoad.outImage, buffer, m_caseDef.size, VK_ACCESS_SHADER_WRITE_BIT, requiredImageLayout, m_caseDef.numLayers);
1541 }
1542 
copyImageToBuffer(VkImage sourceImage,VkBuffer buffer,const IVec3 size,const VkAccessFlags srcAccessMask,const VkImageLayout oldLayout,const deUint32 numLayers)1543 void UploadDownloadExecutor::copyImageToBuffer(VkImage				sourceImage,
1544 											   VkBuffer				buffer,
1545 											   const IVec3			size,
1546 											   const VkAccessFlags	srcAccessMask,
1547 											   const VkImageLayout	oldLayout,
1548 											   const deUint32		numLayers)
1549 {
1550 	// Copy result to host visible buffer for inspection
1551 	const VkImageMemoryBarrier	imageBarrier	=
1552 	{
1553 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
1554 		DE_NULL,									// const void*				pNext;
1555 		srcAccessMask,								// VkAccessFlags			srcAccessMask;
1556 		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
1557 		oldLayout,									// VkImageLayout			oldLayout;
1558 		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
1559 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
1560 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
1561 		sourceImage,								// VkImage					image;
1562 		makeColorSubresourceRange(0, numLayers)		// VkImageSubresourceRange	subresourceRange;
1563 	};
1564 
1565 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1566 		0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1567 
1568 	const VkImageSubresourceLayers	subresource	=
1569 	{
1570 		VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags    aspectMask;
1571 		0u,											// deUint32              mipLevel;
1572 		0u,											// deUint32              baseArrayLayer;
1573 		numLayers,									// deUint32              layerCount;
1574 	};
1575 
1576 	const VkBufferImageCopy			region		=
1577 	{
1578 		0ull,										// VkDeviceSize                bufferOffset;
1579 		0u,											// deUint32                    bufferRowLength;
1580 		0u,											// deUint32                    bufferImageHeight;
1581 		subresource,								// VkImageSubresourceLayers    imageSubresource;
1582 		makeOffset3D(0, 0, 0),						// VkOffset3D                  imageOffset;
1583 		makeExtent3D(size),							// VkExtent3D                  imageExtent;
1584 	};
1585 
1586 	m_vk.cmdCopyImageToBuffer(*m_cmdBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &region);
1587 
1588 	const VkBufferMemoryBarrier	bufferBarrier =
1589 	{
1590 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
1591 		DE_NULL,									// const void*        pNext;
1592 		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
1593 		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
1594 		VK_QUEUE_FAMILY_IGNORED,					// deUint32           srcQueueFamilyIndex;
1595 		VK_QUEUE_FAMILY_IGNORED,					// deUint32           dstQueueFamilyIndex;
1596 		buffer,										// VkBuffer           buffer;
1597 		0ull,										// VkDeviceSize       offset;
1598 		VK_WHOLE_SIZE,								// VkDeviceSize       size;
1599 	};
1600 
1601 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1602 		0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1603 }
1604 
testMutable(Context & context,const CaseDef caseDef)1605 tcu::TestStatus testMutable (Context& context, const CaseDef caseDef)
1606 {
1607 	const DeviceInterface&		vk					= context.getDeviceInterface();
1608 	const VkDevice				device				= context.getDevice();
1609 	Allocator&					allocator			= context.getDefaultAllocator();
1610 
1611 	// Create a color buffer for host-inspection of results
1612 	// For the Copy download method, this is the target of the download, for other
1613 	// download methods, pixel data will be copied to this buffer from the download
1614 	// target
1615 	const VkDeviceSize			colorBufferSize		= caseDef.size.x() * caseDef.size.y() * caseDef.size.z() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.imageFormat));
1616 	const Unique<VkBuffer>		colorBuffer			(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1617 	const UniquePtr<Allocation>	colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1618 	deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1619 	flushAlloc(vk, device, *colorBufferAlloc);
1620 
1621 	// Execute the test
1622 	UploadDownloadExecutor executor(context, device, context.getUniversalQueue(), context.getUniversalQueueFamilyIndex(), caseDef);
1623 	executor.run(context, *colorBuffer);
1624 
1625 	// Verify results
1626 	{
1627 		invalidateAlloc(vk, device, *colorBufferAlloc);
1628 
1629 		// For verification purposes, we use the format of the upload to generate the expected image
1630 		const VkFormat						format			= caseDef.upload == UPLOAD_CLEAR || caseDef.upload == UPLOAD_COPY ? caseDef.imageFormat : caseDef.viewFormat;
1631 		const tcu::TextureFormat			tcuFormat		= mapVkFormat(format);
1632 		const bool							isIntegerFormat	= isUintFormat(format) || isIntFormat(format);
1633 		const tcu::ConstPixelBufferAccess	resultImage		(tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers, colorBufferAlloc->getHostPtr());
1634 		tcu::TextureLevel					textureLevel	(tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers);
1635 		const tcu::PixelBufferAccess		expectedImage	= textureLevel.getAccess();
1636 		generateExpectedImage(expectedImage, caseDef);
1637 
1638 		bool ok;
1639 		if (isIntegerFormat)
1640 			ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1641 		else
1642 			ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1643 		return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1644 	}
1645 }
1646 
checkSupport(Context & context,const CaseDef caseDef)1647 void checkSupport (Context& context, const CaseDef caseDef)
1648 {
1649 	const InstanceInterface&		vki			= context.getInstanceInterface();
1650 	const VkPhysicalDevice			physDevice	= context.getPhysicalDevice();
1651 
1652 	// If this is a VK_KHR_image_format_list test, check that the extension is supported
1653 	if (caseDef.isFormatListTest)
1654 		context.requireDeviceFunctionality("VK_KHR_image_format_list");
1655 
1656 	// Check required features on the format for the required upload/download methods
1657 	VkFormatProperties	imageFormatProps, viewFormatProps;
1658 	vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.imageFormat, &imageFormatProps);
1659 	vki.getPhysicalDeviceFormatProperties(physDevice, caseDef.viewFormat, &viewFormatProps);
1660 
1661 	VkFormatFeatureFlags	viewFormatFeatureFlags = 0u;
1662 	switch (caseDef.upload)
1663 	{
1664 	case UPLOAD_DRAW:
1665 		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
1666 		break;
1667 	case UPLOAD_STORE:
1668 		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1669 		break;
1670 	case UPLOAD_CLEAR:
1671 		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
1672 		break;
1673 	case UPLOAD_COPY:
1674 		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
1675 		break;
1676 	default:
1677 		DE_FATAL("Invalid upload method");
1678 		break;
1679 	}
1680 	switch (caseDef.download)
1681 	{
1682 	case DOWNLOAD_TEXTURE:
1683 		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
1684 		// For the texture case we write the samples read to a separate output image with the same view format
1685 		// so we need to check that we can also use the view format for storage
1686 		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1687 		break;
1688 	case DOWNLOAD_LOAD:
1689 		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
1690 		break;
1691 	case DOWNLOAD_COPY:
1692 		viewFormatFeatureFlags |= VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
1693 		break;
1694 	default:
1695 		DE_FATAL("Invalid download method");
1696 		break;
1697 	}
1698 
1699 	if ((viewFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags)
1700 		TCU_THROW(NotSupportedError, "View format doesn't support upload/download method");
1701 
1702 	const bool haveMaintenance2 = context.isDeviceFunctionalitySupported("VK_KHR_maintenance2");
1703 
1704 	// We don't use the base image for anything other than transfer
1705 	// operations so there are no features to check.  However, The Vulkan
1706 	// 1.0 spec does not allow us to create an image view with usage that
1707 	// is not supported by the main format.  With VK_KHR_maintenance2, we
1708 	// can do this via VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR.
1709 	if ((imageFormatProps.optimalTilingFeatures & viewFormatFeatureFlags) != viewFormatFeatureFlags &&
1710 		!haveMaintenance2)
1711 	{
1712 		TCU_THROW(NotSupportedError, "Image format doesn't support upload/download method");
1713 	}
1714 
1715 	// If no format feature flags are supported, the format itself is not supported,
1716 	// and images of that format cannot be created.
1717 	if (imageFormatProps.optimalTilingFeatures == 0)
1718 	{
1719 		TCU_THROW(NotSupportedError, "Base image format is not supported");
1720 	}
1721 }
1722 
createImageMutableTests(TestContext & testCtx)1723 tcu::TestCaseGroup* createImageMutableTests (TestContext& testCtx)
1724 {
1725 	de::MovePtr<TestCaseGroup> testGroup	(new TestCaseGroup(testCtx, "mutable", "Cases with mutable images"));
1726 	for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1727 	{
1728 		const Texture&					texture					= s_textures[textureNdx];
1729 		de::MovePtr<tcu::TestCaseGroup> groupByImageViewType	(new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1730 
1731 		for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
1732 		for (int viewFormatNdx = 0; viewFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++viewFormatNdx)
1733 		{
1734 			if (imageFormatNdx != viewFormatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[viewFormatNdx]))
1735 			{
1736 				for (int upload = 0; upload < UPLOAD_LAST; upload++)
1737 				{
1738 					if (upload == UPLOAD_STORE && !isFormatImageLoadStoreCapable(s_formats[viewFormatNdx]))
1739 						continue;
1740 
1741 					for (int download = 0; download < DOWNLOAD_LAST; download++)
1742 					{
1743 						if ((download == DOWNLOAD_LOAD || download == DOWNLOAD_TEXTURE) &&
1744 							!isFormatImageLoadStoreCapable(s_formats[viewFormatNdx]))
1745 							continue;
1746 
1747 						CaseDef caseDef =
1748 						{
1749 							texture.type(),
1750 							texture.layerSize(),
1751 							static_cast<deUint32>(texture.numLayers()),
1752 							s_formats[imageFormatNdx],
1753 							s_formats[viewFormatNdx],
1754 							static_cast<enum Upload>(upload),
1755 							static_cast<enum Download>(download),
1756 							false,				// isFormatListTest;
1757 							false,				// isSwapchainImageTest
1758 							vk::wsi::TYPE_LAST	// wsiType
1759 						};
1760 
1761 						std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[viewFormatNdx]) +
1762 							"_" + getUploadString(upload) + "_" + getDownloadString(download);
1763 						addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", checkSupport, initPrograms, testMutable, caseDef);
1764 
1765 						caseDef.isFormatListTest = true;
1766 						caseName += "_format_list";
1767 						addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", checkSupport, initPrograms, testMutable, caseDef);
1768 					}
1769 				}
1770 			}
1771 		}
1772 
1773 		testGroup->addChild(groupByImageViewType.release());
1774 	}
1775 
1776 	return testGroup.release();
1777 }
1778 
1779 typedef vector<VkExtensionProperties> Extensions;
1780 
checkAllSupported(const Extensions & supportedExtensions,const vector<string> & requiredExtensions)1781 void checkAllSupported(const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
1782 {
1783 	for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
1784 		requiredExtName != requiredExtensions.end();
1785 		++requiredExtName)
1786 	{
1787 		if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
1788 			TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
1789 	}
1790 }
1791 
createInstanceWithWsi(Context & context,const Extensions & supportedExtensions,Type wsiType,const VkAllocationCallbacks * pAllocator=DE_NULL)1792 CustomInstance createInstanceWithWsi(Context&						context,
1793 									 const Extensions&				supportedExtensions,
1794 									 Type							wsiType,
1795 									 const VkAllocationCallbacks*	pAllocator = DE_NULL)
1796 {
1797 	vector<string>	extensions;
1798 
1799 	extensions.push_back("VK_KHR_surface");
1800 	extensions.push_back(getExtensionName(wsiType));
1801 
1802 	// VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
1803 	// the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
1804 	// but using them without enabling the extension is not allowed. Thus we have
1805 	// two options:
1806 	//
1807 	// 1) Filter out non-core formats to stay within valid usage.
1808 	//
1809 	// 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
1810 	//
1811 	// We opt for (2) as it provides basic coverage for the extension as a bonus.
1812 	if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
1813 		extensions.push_back("VK_EXT_swapchain_colorspace");
1814 
1815 	checkAllSupported(supportedExtensions, extensions);
1816 
1817 	return createCustomInstanceWithExtensions(context, extensions, pAllocator);
1818 }
1819 
1820 
createDeviceWithWsi(const PlatformInterface & vkp,VkInstance instance,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const Extensions & supportedExtensions,const deUint32 queueFamilyIndex,const VkAllocationCallbacks * pAllocator,bool enableValidation)1821 Move<VkDevice> createDeviceWithWsi(const PlatformInterface&		vkp,
1822 								   VkInstance					instance,
1823 								   const InstanceInterface&		vki,
1824 								   VkPhysicalDevice				physicalDevice,
1825 								   const Extensions&			supportedExtensions,
1826 								   const deUint32				queueFamilyIndex,
1827 								   const VkAllocationCallbacks*	pAllocator,
1828 								   bool							enableValidation)
1829 {
1830 	const float						queuePriorities[] = { 1.0f };
1831 	const VkDeviceQueueCreateInfo	queueInfos[] =
1832 	{
1833 		{
1834 			VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
1835 			DE_NULL,
1836 			(VkDeviceQueueCreateFlags)0,
1837 			queueFamilyIndex,
1838 			DE_LENGTH_OF_ARRAY(queuePriorities),
1839 			&queuePriorities[0]
1840 		}
1841 	};
1842 	VkPhysicalDeviceFeatures		features;
1843 	deMemset(&features, 0x0, sizeof(features));
1844 
1845 	const char* const				extensions[] = { "VK_KHR_swapchain", "VK_KHR_swapchain_mutable_format" };
1846 
1847 	const VkDeviceCreateInfo		deviceParams =
1848 	{
1849 		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
1850 		DE_NULL,
1851 		(VkDeviceCreateFlags)0,
1852 		DE_LENGTH_OF_ARRAY(queueInfos),
1853 		&queueInfos[0],
1854 		0u,									// enabledLayerCount
1855 		DE_NULL,							// ppEnabledLayerNames
1856 		DE_LENGTH_OF_ARRAY(extensions),		// enabledExtensionCount
1857 		DE_ARRAY_BEGIN(extensions),			// ppEnabledExtensionNames
1858 		&features
1859 	};
1860 
1861 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
1862 	{
1863 		if (!isExtensionSupported(supportedExtensions, RequiredExtension(extensions[ndx])))
1864 			TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
1865 	}
1866 
1867 	return createCustomDevice(enableValidation, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
1868 }
1869 
1870 struct InstanceHelper
1871 {
1872 	const vector<VkExtensionProperties>	supportedExtensions;
1873 	const CustomInstance				instance;
1874 	const InstanceDriver&				vki;
1875 
InstanceHelpervkt::image::InstanceHelper1876 	InstanceHelper(Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
1877 		: supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(),
1878 			DE_NULL))
1879 		, instance(createInstanceWithWsi(context,
1880 			supportedExtensions,
1881 			wsiType,
1882 			pAllocator))
1883 		, vki(instance.getDriver())
1884 	{}
1885 };
1886 
1887 
1888 struct DeviceHelper
1889 {
1890 	const VkPhysicalDevice	physicalDevice;
1891 	const deUint32			queueFamilyIndex;
1892 	const Unique<VkDevice>	device;
1893 	const DeviceDriver		vkd;
1894 	const VkQueue			queue;
1895 
DeviceHelpervkt::image::DeviceHelper1896 	DeviceHelper(Context&						context,
1897 		const InstanceInterface&		vki,
1898 		VkInstance					instance,
1899 		VkSurfaceKHR					surface,
1900 		const VkAllocationCallbacks*	pAllocator = DE_NULL)
1901 		: physicalDevice(chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
1902 		, queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, surface))
1903 		, device(createDeviceWithWsi(context.getPlatformInterface(),
1904 			context.getInstance(),
1905 			vki,
1906 			physicalDevice,
1907 			enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
1908 			queueFamilyIndex,
1909 			pAllocator,
1910 			context.getTestContext().getCommandLine().isValidationEnabled()))
1911 		, vkd(context.getPlatformInterface(), context.getInstance(), *device)
1912 		, queue(getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
1913 	{
1914 	}
1915 };
1916 
createDisplay(const vk::Platform & platform,const Extensions & supportedExtensions,Type wsiType)1917 MovePtr<Display> createDisplay(const vk::Platform&	platform,
1918 	const Extensions&	supportedExtensions,
1919 	Type				wsiType)
1920 {
1921 	try
1922 	{
1923 		return MovePtr<Display>(platform.createWsiDisplay(wsiType));
1924 	}
1925 	catch (const tcu::NotSupportedError& e)
1926 	{
1927 		if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
1928 		    platform.hasDisplay(wsiType))
1929 		{
1930 			// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
1931 			// must support creating native display & window for that WSI type.
1932 			throw tcu::TestError(e.getMessage());
1933 		}
1934 		else
1935 			throw;
1936 	}
1937 }
1938 
createWindow(const Display & display,const Maybe<UVec2> & initialSize)1939 MovePtr<Window> createWindow(const Display& display, const Maybe<UVec2>& initialSize)
1940 {
1941 	try
1942 	{
1943 		return MovePtr<Window>(display.createWindow(initialSize));
1944 	}
1945 	catch (const tcu::NotSupportedError& e)
1946 	{
1947 		// See createDisplay - assuming that wsi::Display was supported platform port
1948 		// should also support creating a window.
1949 		throw tcu::TestError(e.getMessage());
1950 	}
1951 }
1952 
1953 struct NativeObjects
1954 {
1955 	const UniquePtr<Display>	display;
1956 	const UniquePtr<Window>		window;
1957 
NativeObjectsvkt::image::NativeObjects1958 	NativeObjects(Context&				context,
1959 		const Extensions&	supportedExtensions,
1960 		Type					wsiType,
1961 		const Maybe<UVec2>&	initialWindowSize = tcu::nothing<UVec2>())
1962 		: display(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
1963 		, window(createWindow(*display, initialWindowSize))
1964 	{}
1965 };
1966 
makeSwapchain(const DeviceInterface & vk,const VkDevice device,const vk::wsi::Type wsiType,const VkSurfaceKHR surface,const VkSurfaceCapabilitiesKHR capabilities,const VkSurfaceFormatKHR surfaceFormat,const VkFormat viewFormat,const deUint32 numLayers,const VkImageUsageFlags usage,const tcu::UVec2 & desiredSize,deUint32 desiredImageCount)1967 Move<VkSwapchainKHR> makeSwapchain(const DeviceInterface&		vk,
1968 									const VkDevice				device,
1969 									const vk::wsi::Type			wsiType,
1970 									const VkSurfaceKHR			surface,
1971 									const VkSurfaceCapabilitiesKHR		capabilities,
1972 									const VkSurfaceFormatKHR	surfaceFormat,
1973 									const VkFormat				viewFormat,
1974 									const deUint32				numLayers,
1975 									const VkImageUsageFlags		usage,
1976 									const tcu::UVec2&			desiredSize,
1977 									deUint32					desiredImageCount
1978 )
1979 {
1980 	const VkFormat formatList[2] =
1981 	{
1982 		surfaceFormat.format,
1983 		viewFormat
1984 	};
1985 
1986 	const VkImageFormatListCreateInfo formatListInfo =
1987 	{
1988 		VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR,	// VkStructureType			sType;
1989 		DE_NULL,												// const void*				pNext;
1990 		2u,														// deUint32					viewFormatCount
1991 		formatList												// const VkFormat*			pViewFormats
1992 	};
1993 
1994 	const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
1995 	const PlatformProperties&			platformProperties = getPlatformProperties(wsiType);
1996 
1997 	const VkSwapchainCreateInfoKHR		swapchainInfo =
1998 	{
1999 		VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,		// VkStructureType					sType;
2000 		&formatListInfo,									// const void*						pNext;
2001 		VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR,			// VkSwapchainCreateFlagsKHR		flags;
2002 		surface,											// VkSurfaceKHR						surface;
2003 		de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount), // deUint32						minImageCount;
2004 		surfaceFormat.format,								// VkFormat							imageFormat;
2005 		surfaceFormat.colorSpace,							// VkColorSpaceKHR					imageColorSpace;
2006 		(platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
2007 		? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),	// VkExtent2D						imageExtent;
2008 		numLayers,											// deUint32							imageArrayLayers;
2009 		usage,												// VkImageUsageFlags				imageUsage;
2010 		VK_SHARING_MODE_EXCLUSIVE,							// VkSharingMode					imageSharingMode;
2011 		0u,													// deUint32							queueFamilyIndexCount;
2012 		(const deUint32*)DE_NULL,							// const deUint32*					pQueueFamilyIndices;
2013 		transform,											// VkSurfaceTransformFlagBitsKHR	preTransform;
2014 		VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,					// VkCompositeAlphaFlagBitsKHR		compositeAlpha;
2015 		VK_PRESENT_MODE_FIFO_KHR,							// VkPresentModeKHR					presentMode;
2016 		VK_FALSE,											// VkBool32							clipped;
2017 		(VkSwapchainKHR)0									// VkSwapchainKHR					oldSwapchain;
2018 	};
2019 
2020 	return createSwapchainKHR(vk, device, &swapchainInfo);
2021 }
2022 
testSwapchainMutable(Context & context,CaseDef caseDef)2023 tcu::TestStatus testSwapchainMutable(Context& context, CaseDef caseDef)
2024 {
2025 	const Type						wsiType(caseDef.wsiType);
2026 	const tcu::UVec2				desiredSize(256, 256);
2027 	const InstanceHelper			instHelper(context, wsiType);
2028 	const NativeObjects				native(context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
2029 	const Unique<VkSurfaceKHR>		surface(createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
2030 	const DeviceHelper				devHelper(context, instHelper.vki, instHelper.instance, *surface);
2031 	const DeviceInterface&			vk = devHelper.vkd;
2032 	const InstanceDriver&			vki = instHelper.vki;
2033 	const VkDevice					device = *devHelper.device;
2034 	const VkPhysicalDevice			physDevice = devHelper.physicalDevice;
2035 	SimpleAllocator					allocator(vk, device, getPhysicalDeviceMemoryProperties(vki, context.getPhysicalDevice()));
2036 
2037 	const VkImageUsageFlags			imageUsage = getImageUsageForTestCase(caseDef);
2038 
2039 	{
2040 		VkImageFormatProperties properties;
2041 		VkResult				result;
2042 
2043 		result = vki.getPhysicalDeviceImageFormatProperties(physDevice, caseDef.imageFormat, getImageType(caseDef.imageType), VK_IMAGE_TILING_OPTIMAL, imageUsage, 0, &properties);
2044 
2045 		if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
2046 		{
2047 			TCU_THROW(NotSupportedError, "Image format is not supported for required usage");
2048 		}
2049 
2050 		result = vki.getPhysicalDeviceImageFormatProperties(physDevice, caseDef.viewFormat, getImageType(caseDef.imageType), VK_IMAGE_TILING_OPTIMAL, imageUsage, 0, &properties);
2051 
2052 		if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
2053 		{
2054 			TCU_THROW(NotSupportedError, "Image view format is not supported for required usage");
2055 		}
2056 	}
2057 
2058 	const VkSurfaceCapabilitiesKHR		capabilities = getPhysicalDeviceSurfaceCapabilities(vki,
2059 																							physDevice,
2060 																							*surface);
2061 
2062 	if (caseDef.numLayers > capabilities.maxImageArrayLayers)
2063 		caseDef.numLayers = capabilities.maxImageArrayLayers;
2064 
2065 	// Check support for requested formats by swapchain surface
2066 	const vector<VkSurfaceFormatKHR>surfaceFormats = getPhysicalDeviceSurfaceFormats(vki,
2067 																					 physDevice,
2068 																					 *surface);
2069 
2070 	const VkSurfaceFormatKHR*		surfaceFormat = DE_NULL;
2071 	const VkFormat*					viewFormat = DE_NULL;
2072 
2073 	for (vector<VkSurfaceFormatKHR>::size_type i = 0; i < surfaceFormats.size(); i++)
2074 	{
2075 		if (surfaceFormats[i].format == caseDef.imageFormat)
2076 			surfaceFormat = &surfaceFormats[i];
2077 
2078 		if (surfaceFormats[i].format == caseDef.viewFormat)
2079 			viewFormat = &surfaceFormats[i].format;
2080 	}
2081 
2082 	if (surfaceFormat == DE_NULL)
2083 		TCU_THROW(NotSupportedError, "Image format is not supported by swapchain.");
2084 
2085 	if (viewFormat == DE_NULL)
2086 		TCU_THROW(NotSupportedError, "Image view format is not supported by swapchain.");
2087 
2088 	if ((capabilities.supportedUsageFlags & imageUsage) != imageUsage)
2089 		TCU_THROW(NotSupportedError, "Image usage request not supported by swapchain.");
2090 
2091 	const Unique<VkSwapchainKHR>	swapchain(
2092 		makeSwapchain(
2093 			vk,
2094 			device,
2095 			caseDef.wsiType,
2096 			*surface,
2097 			capabilities,
2098 			*surfaceFormat,
2099 			caseDef.viewFormat,
2100 			caseDef.numLayers,
2101 			imageUsage,
2102 			desiredSize,
2103 			2)
2104 		);
2105 	const vector<VkImage>			swapchainImages = getSwapchainImages(vk, device, *swapchain);
2106 
2107 	// Create a color buffer for host-inspection of results
2108 	// For the Copy download method, this is the target of the download, for other
2109 	// download methods, pixel data will be copied to this buffer from the download
2110 	// target
2111 	const VkDeviceSize			colorBufferSize = caseDef.size.x() * caseDef.size.y() * caseDef.size.z() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.imageFormat));
2112 	const Unique<VkBuffer>		colorBuffer(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2113 	const UniquePtr<Allocation>	colorBufferAlloc(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
2114 	deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
2115 	flushAlloc(vk, device, *colorBufferAlloc);
2116 
2117 
2118 	// Execute the test
2119 	UploadDownloadExecutor executor(context, device, devHelper.queue, devHelper.queueFamilyIndex, caseDef);
2120 
2121 	executor.runSwapchain(context, *colorBuffer, swapchainImages[0]);
2122 
2123 	// Verify results
2124 	{
2125 		invalidateAlloc(vk, device, *colorBufferAlloc);
2126 
2127 		// For verification purposes, we use the format of the upload to generate the expected image
2128 		const VkFormat						format = caseDef.upload == UPLOAD_CLEAR || caseDef.upload == UPLOAD_COPY ? caseDef.imageFormat : caseDef.viewFormat;
2129 		const tcu::TextureFormat			tcuFormat = mapVkFormat(format);
2130 		const bool							isIntegerFormat = isUintFormat(format) || isIntFormat(format);
2131 		const tcu::ConstPixelBufferAccess	resultImage(tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers, colorBufferAlloc->getHostPtr());
2132 		tcu::TextureLevel					textureLevel(tcuFormat, caseDef.size.x(), caseDef.size.y(), caseDef.numLayers);
2133 		const tcu::PixelBufferAccess		expectedImage = textureLevel.getAccess();
2134 		generateExpectedImage(expectedImage, caseDef);
2135 
2136 		bool ok;
2137 		if (isIntegerFormat)
2138 			ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
2139 		else
2140 			ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
2141 		return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
2142 	}
2143 }
2144 
createSwapchainImageMutableTests(TestContext & testCtx)2145 tcu::TestCaseGroup* createSwapchainImageMutableTests(TestContext& testCtx)
2146 {
2147 	de::MovePtr<TestCaseGroup> testGroup(new TestCaseGroup(testCtx, "swapchain_mutable", "Cases with swapchain mutable images"));
2148 
2149 	for (int typeNdx = 0; typeNdx < vk::wsi::TYPE_LAST; ++typeNdx)
2150 	{
2151 		const vk::wsi::Type	wsiType = (vk::wsi::Type)typeNdx;
2152 
2153 		de::MovePtr<TestCaseGroup> testGroupWsi(new TestCaseGroup(testCtx, getName(wsiType), ""));
2154 
2155 		for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2156 		{
2157 			const Texture&					texture = s_textures[textureNdx];
2158 			de::MovePtr<tcu::TestCaseGroup> groupByImageViewType(new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2159 
2160 			for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_swapchainFormats); ++imageFormatNdx)
2161 				for (int viewFormatNdx = 0; viewFormatNdx < DE_LENGTH_OF_ARRAY(s_swapchainFormats); ++viewFormatNdx)
2162 				{
2163 					if (imageFormatNdx != viewFormatNdx && formatsAreCompatible(s_swapchainFormats[imageFormatNdx], s_swapchainFormats[viewFormatNdx]))
2164 					{
2165 						for (int upload = 0; upload < UPLOAD_LAST; upload++)
2166 						{
2167 							if (upload == UPLOAD_STORE && !isFormatImageLoadStoreCapable(s_swapchainFormats[viewFormatNdx]))
2168 								continue;
2169 
2170 							for (int download = 0; download < DOWNLOAD_LAST; download++)
2171 							{
2172 								if ((download == DOWNLOAD_LOAD || download == DOWNLOAD_TEXTURE) &&
2173 									!isFormatImageLoadStoreCapable(s_swapchainFormats[viewFormatNdx]))
2174 									continue;
2175 
2176 								CaseDef caseDef =
2177 								{
2178 									texture.type(),
2179 									texture.layerSize(),
2180 									static_cast<deUint32>(texture.numLayers()),
2181 									s_swapchainFormats[imageFormatNdx],
2182 									s_swapchainFormats[viewFormatNdx],
2183 									static_cast<enum Upload>(upload),
2184 									static_cast<enum Download>(download),
2185 									true,		// isFormatListTest;
2186 									true,		// isSwapchainImageTest
2187 									wsiType
2188 								};
2189 
2190 								std::string caseName = getFormatShortString(s_swapchainFormats[imageFormatNdx]) + "_" + getFormatShortString(s_swapchainFormats[viewFormatNdx]) +
2191 									"_" + getUploadString(upload) + "_" + getDownloadString(download) + "_format_list";
2192 
2193 								addFunctionCaseWithPrograms(groupByImageViewType.get(), caseName, "", checkSupport, initPrograms, testSwapchainMutable, caseDef);
2194 							}
2195 						}
2196 					}
2197 				}
2198 
2199 			testGroupWsi->addChild(groupByImageViewType.release());
2200 		}
2201 
2202 		testGroup->addChild(testGroupWsi.release());
2203 	}
2204 	return testGroup.release();
2205 }
2206 
2207 } // image
2208 } // vkt
2209