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