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