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