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