1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 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  vktSparseResourcesTestsUtil.cpp
21 * \brief Sparse Resources Tests Utility Classes
22 *//*--------------------------------------------------------------------*/
23
24#include "vktSparseResourcesTestsUtil.hpp"
25#include "vkQueryUtil.hpp"
26#include "vkTypeUtil.hpp"
27#include "tcuTextureUtil.hpp"
28
29#include <deMath.h>
30
31using namespace vk;
32
33namespace vkt
34{
35namespace sparse
36{
37
38tcu::UVec3 getShaderGridSize (const ImageType imageType, const tcu::UVec3& imageSize, const deUint32 mipLevel)
39{
40	const deUint32 mipLevelX = std::max(imageSize.x() >> mipLevel, 1u);
41	const deUint32 mipLevelY = std::max(imageSize.y() >> mipLevel, 1u);
42	const deUint32 mipLevelZ = std::max(imageSize.z() >> mipLevel, 1u);
43
44	switch (imageType)
45	{
46	case IMAGE_TYPE_1D:
47		return tcu::UVec3(mipLevelX, 1u, 1u);
48
49	case IMAGE_TYPE_BUFFER:
50		return tcu::UVec3(imageSize.x(), 1u, 1u);
51
52	case IMAGE_TYPE_1D_ARRAY:
53		return tcu::UVec3(mipLevelX, imageSize.z(), 1u);
54
55	case IMAGE_TYPE_2D:
56		return tcu::UVec3(mipLevelX, mipLevelY, 1u);
57
58	case IMAGE_TYPE_2D_ARRAY:
59		return tcu::UVec3(mipLevelX, mipLevelY, imageSize.z());
60
61	case IMAGE_TYPE_3D:
62		return tcu::UVec3(mipLevelX, mipLevelY, mipLevelZ);
63
64	case IMAGE_TYPE_CUBE:
65		return tcu::UVec3(mipLevelX, mipLevelY, 6u);
66
67	case IMAGE_TYPE_CUBE_ARRAY:
68		return tcu::UVec3(mipLevelX, mipLevelY, 6u * imageSize.z());
69
70	default:
71		DE_FATAL("Unknown image type");
72		return tcu::UVec3(1u, 1u, 1u);
73	}
74}
75
76tcu::UVec3 getLayerSize (const ImageType imageType, const tcu::UVec3& imageSize)
77{
78	switch (imageType)
79	{
80	case IMAGE_TYPE_1D:
81	case IMAGE_TYPE_1D_ARRAY:
82	case IMAGE_TYPE_BUFFER:
83		return tcu::UVec3(imageSize.x(), 1u, 1u);
84
85	case IMAGE_TYPE_2D:
86	case IMAGE_TYPE_2D_ARRAY:
87	case IMAGE_TYPE_CUBE:
88	case IMAGE_TYPE_CUBE_ARRAY:
89		return tcu::UVec3(imageSize.x(), imageSize.y(), 1u);
90
91	case IMAGE_TYPE_3D:
92		return tcu::UVec3(imageSize.x(), imageSize.y(), imageSize.z());
93
94	default:
95		DE_FATAL("Unknown image type");
96		return tcu::UVec3(1u, 1u, 1u);
97	}
98}
99
100deUint32 getNumLayers (const ImageType imageType, const tcu::UVec3& imageSize)
101{
102	switch (imageType)
103	{
104	case IMAGE_TYPE_1D:
105	case IMAGE_TYPE_2D:
106	case IMAGE_TYPE_3D:
107	case IMAGE_TYPE_BUFFER:
108		return 1u;
109
110	case IMAGE_TYPE_1D_ARRAY:
111	case IMAGE_TYPE_2D_ARRAY:
112		return imageSize.z();
113
114	case IMAGE_TYPE_CUBE:
115		return 6u;
116
117	case IMAGE_TYPE_CUBE_ARRAY:
118		return imageSize.z() * 6u;
119
120	default:
121		DE_FATAL("Unknown image type");
122		return 0u;
123	}
124}
125
126deUint32 getNumPixels (const ImageType imageType, const tcu::UVec3& imageSize)
127{
128	const tcu::UVec3 gridSize = getShaderGridSize(imageType, imageSize);
129
130	return gridSize.x() * gridSize.y() * gridSize.z();
131}
132
133deUint32 getDimensions (const ImageType imageType)
134{
135	switch (imageType)
136	{
137	case IMAGE_TYPE_1D:
138	case IMAGE_TYPE_BUFFER:
139		return 1u;
140
141	case IMAGE_TYPE_1D_ARRAY:
142	case IMAGE_TYPE_2D:
143		return 2u;
144
145	case IMAGE_TYPE_2D_ARRAY:
146	case IMAGE_TYPE_CUBE:
147	case IMAGE_TYPE_CUBE_ARRAY:
148	case IMAGE_TYPE_3D:
149		return 3u;
150
151	default:
152		DE_FATAL("Unknown image type");
153		return 0u;
154	}
155}
156
157deUint32 getLayerDimensions (const ImageType imageType)
158{
159	switch (imageType)
160	{
161	case IMAGE_TYPE_1D:
162	case IMAGE_TYPE_BUFFER:
163	case IMAGE_TYPE_1D_ARRAY:
164		return 1u;
165
166	case IMAGE_TYPE_2D:
167	case IMAGE_TYPE_2D_ARRAY:
168	case IMAGE_TYPE_CUBE:
169	case IMAGE_TYPE_CUBE_ARRAY:
170		return 2u;
171
172	case IMAGE_TYPE_3D:
173		return 3u;
174
175	default:
176		DE_FATAL("Unknown image type");
177		return 0u;
178	}
179}
180
181bool isImageSizeSupported (const InstanceInterface& instance, const VkPhysicalDevice physicalDevice, const ImageType imageType, const tcu::UVec3& imageSize)
182{
183	const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice);
184
185	switch (imageType)
186	{
187		case IMAGE_TYPE_1D:
188			return	imageSize.x() <= deviceProperties.limits.maxImageDimension1D;
189		case IMAGE_TYPE_1D_ARRAY:
190			return	imageSize.x() <= deviceProperties.limits.maxImageDimension1D &&
191					imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
192		case IMAGE_TYPE_2D:
193			return	imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
194					imageSize.y() <= deviceProperties.limits.maxImageDimension2D;
195		case IMAGE_TYPE_2D_ARRAY:
196			return	imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
197					imageSize.y() <= deviceProperties.limits.maxImageDimension2D &&
198					imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
199		case IMAGE_TYPE_CUBE:
200			return	imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
201					imageSize.y() <= deviceProperties.limits.maxImageDimensionCube;
202		case IMAGE_TYPE_CUBE_ARRAY:
203			return	imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
204					imageSize.y() <= deviceProperties.limits.maxImageDimensionCube &&
205					imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
206		case IMAGE_TYPE_3D:
207			return	imageSize.x() <= deviceProperties.limits.maxImageDimension3D &&
208					imageSize.y() <= deviceProperties.limits.maxImageDimension3D &&
209					imageSize.z() <= deviceProperties.limits.maxImageDimension3D;
210		case IMAGE_TYPE_BUFFER:
211			return true;
212		default:
213			DE_FATAL("Unknown image type");
214			return false;
215	}
216}
217
218VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize			bufferSize,
219										 const VkBufferUsageFlags	usage)
220{
221	const VkBufferCreateInfo bufferCreateInfo =
222	{
223		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
224		DE_NULL,								// const void*			pNext;
225		0u,										// VkBufferCreateFlags	flags;
226		bufferSize,								// VkDeviceSize			size;
227		usage,									// VkBufferUsageFlags	usage;
228		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
229		0u,										// deUint32				queueFamilyIndexCount;
230		DE_NULL,								// const deUint32*		pQueueFamilyIndices;
231	};
232	return bufferCreateInfo;
233}
234
235VkBufferImageCopy makeBufferImageCopy (const VkExtent3D		extent,
236									   const deUint32		layerCount,
237									   const deUint32		mipmapLevel,
238									   const VkDeviceSize	bufferOffset)
239{
240	const VkBufferImageCopy copyParams =
241	{
242		bufferOffset,																		//	VkDeviceSize				bufferOffset;
243		0u,																					//	deUint32					bufferRowLength;
244		0u,																					//	deUint32					bufferImageHeight;
245		makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, mipmapLevel, 0u, layerCount),	//	VkImageSubresourceLayers	imageSubresource;
246		makeOffset3D(0, 0, 0),																//	VkOffset3D					imageOffset;
247		extent,																				//	VkExtent3D					imageExtent;
248	};
249	return copyParams;
250}
251
252Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
253{
254	const VkCommandPoolCreateInfo commandPoolParams =
255	{
256		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType			sType;
257		DE_NULL,											// const void*				pNext;
258		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCommandPoolCreateFlags	flags;
259		queueFamilyIndex,									// deUint32					queueFamilyIndex;
260	};
261	return createCommandPool(vk, device, &commandPoolParams);
262}
263
264Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&		vk,
265										   const VkDevice				device,
266										   const VkDescriptorSetLayout	descriptorSetLayout)
267{
268	const VkPipelineLayoutCreateInfo pipelineLayoutParams =
269	{
270		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,						// VkStructureType					sType;
271		DE_NULL,															// const void*						pNext;
272		0u,																	// VkPipelineLayoutCreateFlags		flags;
273		(descriptorSetLayout != DE_NULL ? 1u : 0u),							// deUint32							setLayoutCount;
274		(descriptorSetLayout != DE_NULL ? &descriptorSetLayout : DE_NULL),	// const VkDescriptorSetLayout*		pSetLayouts;
275		0u,																	// deUint32							pushConstantRangeCount;
276		DE_NULL,															// const VkPushConstantRange*		pPushConstantRanges;
277	};
278	return createPipelineLayout(vk, device, &pipelineLayoutParams);
279}
280
281Move<VkPipeline> makeComputePipeline (const DeviceInterface&		vk,
282									  const VkDevice				device,
283									  const VkPipelineLayout		pipelineLayout,
284									  const VkShaderModule			shaderModule,
285									  const VkSpecializationInfo*	specializationInfo)
286{
287	const VkPipelineShaderStageCreateInfo pipelineShaderStageParams =
288	{
289		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
290		DE_NULL,												// const void*							pNext;
291		0u,														// VkPipelineShaderStageCreateFlags		flags;
292		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
293		shaderModule,											// VkShaderModule						module;
294		"main",													// const char*							pName;
295		specializationInfo,										// const VkSpecializationInfo*			pSpecializationInfo;
296	};
297	const VkComputePipelineCreateInfo pipelineCreateInfo =
298	{
299		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,		// VkStructureType					sType;
300		DE_NULL,											// const void*						pNext;
301		0u,													// VkPipelineCreateFlags			flags;
302		pipelineShaderStageParams,							// VkPipelineShaderStageCreateInfo	stage;
303		pipelineLayout,										// VkPipelineLayout					layout;
304		DE_NULL,											// VkPipeline						basePipelineHandle;
305		0,													// deInt32							basePipelineIndex;
306	};
307	return createComputePipeline(vk, device, DE_NULL , &pipelineCreateInfo);
308}
309
310Move<VkBufferView> makeBufferView (const DeviceInterface&	vk,
311								   const VkDevice			vkDevice,
312								   const VkBuffer			buffer,
313								   const VkFormat			format,
314								   const VkDeviceSize		offset,
315								   const VkDeviceSize		size)
316{
317	const VkBufferViewCreateInfo bufferViewParams =
318	{
319		VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,	// VkStructureType			sType;
320		DE_NULL,									// const void*				pNext;
321		0u,											// VkBufferViewCreateFlags	flags;
322		buffer,										// VkBuffer					buffer;
323		format,										// VkFormat					format;
324		offset,										// VkDeviceSize				offset;
325		size,										// VkDeviceSize				range;
326	};
327	return createBufferView(vk, vkDevice, &bufferViewParams);
328}
329
330Move<VkImageView> makeImageView (const DeviceInterface&			vk,
331								 const VkDevice					vkDevice,
332								 const VkImage					image,
333								 const VkImageViewType			imageViewType,
334								 const VkFormat					format,
335								 const VkImageSubresourceRange	subresourceRange)
336{
337	const VkImageViewCreateInfo imageViewParams =
338	{
339		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
340		DE_NULL,										// const void*				pNext;
341		0u,												// VkImageViewCreateFlags	flags;
342		image,											// VkImage					image;
343		imageViewType,									// VkImageViewType			viewType;
344		format,											// VkFormat					format;
345		makeComponentMappingRGBA(),						// VkComponentMapping		components;
346		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
347	};
348	return createImageView(vk, vkDevice, &imageViewParams);
349}
350
351Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface&			vk,
352										 const VkDevice					device,
353										 const VkDescriptorPool			descriptorPool,
354										 const VkDescriptorSetLayout	setLayout)
355{
356	const VkDescriptorSetAllocateInfo allocateParams =
357	{
358		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
359		DE_NULL,											// const void*					pNext;
360		descriptorPool,										// VkDescriptorPool				descriptorPool;
361		1u,													// deUint32						setLayoutCount;
362		&setLayout,											// const VkDescriptorSetLayout*	pSetLayouts;
363	};
364	return allocateDescriptorSet(vk, device, &allocateParams);
365}
366
367Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&		vk,
368									 const VkDevice				device,
369									 const VkRenderPass			renderPass,
370									 const deUint32				attachmentCount,
371									 const VkImageView*			pAttachments,
372									 const deUint32				width,
373									 const deUint32				height,
374									 const deUint32				layers)
375{
376	const VkFramebufferCreateInfo framebufferInfo =
377	{
378		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType                             sType;
379		DE_NULL,										// const void*                                 pNext;
380		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags                    flags;
381		renderPass,										// VkRenderPass                                renderPass;
382		attachmentCount,								// uint32_t                                    attachmentCount;
383		pAttachments,									// const VkImageView*                          pAttachments;
384		width,											// uint32_t                                    width;
385		height,											// uint32_t                                    height;
386		layers,											// uint32_t                                    layers;
387	};
388
389	return createFramebuffer(vk, device, &framebufferInfo);
390}
391
392VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags	srcAccessMask,
393											   const VkAccessFlags	dstAccessMask,
394											   const VkBuffer		buffer,
395											   const VkDeviceSize	offset,
396											   const VkDeviceSize	bufferSizeBytes)
397{
398	const VkBufferMemoryBarrier barrier =
399	{
400		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
401		DE_NULL,									// const void*		pNext;
402		srcAccessMask,								// VkAccessFlags	srcAccessMask;
403		dstAccessMask,								// VkAccessFlags	dstAccessMask;
404		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
405		VK_QUEUE_FAMILY_IGNORED,					// deUint32			destQueueFamilyIndex;
406		buffer,										// VkBuffer			buffer;
407		offset,										// VkDeviceSize		offset;
408		bufferSizeBytes,							// VkDeviceSize		size;
409	};
410	return barrier;
411}
412
413VkImageMemoryBarrier makeImageMemoryBarrier	(const VkAccessFlags			srcAccessMask,
414											 const VkAccessFlags			dstAccessMask,
415											 const VkImageLayout			oldLayout,
416											 const VkImageLayout			newLayout,
417											 const VkImage					image,
418											 const VkImageSubresourceRange	subresourceRange)
419{
420	const VkImageMemoryBarrier barrier =
421	{
422		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
423		DE_NULL,								// const void*				pNext;
424		srcAccessMask,							// VkAccessFlags			outputMask;
425		dstAccessMask,							// VkAccessFlags			inputMask;
426		oldLayout,								// VkImageLayout			oldLayout;
427		newLayout,								// VkImageLayout			newLayout;
428		VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
429		VK_QUEUE_FAMILY_IGNORED,				// deUint32					destQueueFamilyIndex;
430		image,									// VkImage					image;
431		subresourceRange,						// VkImageSubresourceRange	subresourceRange;
432	};
433	return barrier;
434}
435
436VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags			srcAccessMask,
437											 const VkAccessFlags			dstAccessMask,
438											 const VkImageLayout			oldLayout,
439											 const VkImageLayout			newLayout,
440											 const deUint32					srcQueueFamilyIndex,
441											 const deUint32					destQueueFamilyIndex,
442											 const VkImage					image,
443											 const VkImageSubresourceRange	subresourceRange)
444{
445	const VkImageMemoryBarrier barrier =
446	{
447		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
448		DE_NULL,								// const void*				pNext;
449		srcAccessMask,							// VkAccessFlags			outputMask;
450		dstAccessMask,							// VkAccessFlags			inputMask;
451		oldLayout,								// VkImageLayout			oldLayout;
452		newLayout,								// VkImageLayout			newLayout;
453		srcQueueFamilyIndex,					// deUint32					srcQueueFamilyIndex;
454		destQueueFamilyIndex,					// deUint32					destQueueFamilyIndex;
455		image,									// VkImage					image;
456		subresourceRange,						// VkImageSubresourceRange	subresourceRange;
457	};
458	return barrier;
459}
460
461VkMemoryBarrier makeMemoryBarrier (const VkAccessFlags	srcAccessMask,
462									   const VkAccessFlags	dstAccessMask)
463{
464	const VkMemoryBarrier barrier =
465	{
466		VK_STRUCTURE_TYPE_MEMORY_BARRIER,	// VkStructureType			sType;
467		DE_NULL,							// const void*				pNext;
468		srcAccessMask,						// VkAccessFlags			outputMask;
469		dstAccessMask,						// VkAccessFlags			inputMask;
470	};
471	return barrier;
472}
473
474de::MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement)
475{
476	de::MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement);
477	VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset()));
478	return alloc;
479}
480
481de::MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBuffer buffer, const MemoryRequirement requirement)
482{
483	de::MovePtr<Allocation> alloc(allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), requirement));
484	VK_CHECK(vk.bindBufferMemory(device, buffer, alloc->getMemory(), alloc->getOffset()));
485	return alloc;
486}
487
488void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
489{
490	const VkCommandBufferBeginInfo commandBufBeginParams =
491	{
492		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
493		DE_NULL,										// const void*						pNext;
494		0u,												// VkCommandBufferUsageFlags		flags;
495		(const VkCommandBufferInheritanceInfo*)DE_NULL,
496	};
497	VK_CHECK(vk.beginCommandBuffer(commandBuffer, &commandBufBeginParams));
498}
499
500void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
501{
502	VK_CHECK(vk.endCommandBuffer(commandBuffer));
503}
504
505void submitCommands (const DeviceInterface&			vk,
506					 const VkQueue					queue,
507					 const VkCommandBuffer			commandBuffer,
508					 const deUint32					waitSemaphoreCount,
509					 const VkSemaphore*				pWaitSemaphores,
510					 const VkPipelineStageFlags*	pWaitDstStageMask,
511					 const deUint32					signalSemaphoreCount,
512					 const VkSemaphore*				pSignalSemaphores)
513{
514	const VkSubmitInfo submitInfo =
515	{
516		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
517		DE_NULL,						// const void*					pNext;
518		waitSemaphoreCount,				// deUint32						waitSemaphoreCount;
519		pWaitSemaphores,				// const VkSemaphore*			pWaitSemaphores;
520		pWaitDstStageMask,				// const VkPipelineStageFlags*	pWaitDstStageMask;
521		1u,								// deUint32						commandBufferCount;
522		&commandBuffer,					// const VkCommandBuffer*		pCommandBuffers;
523		signalSemaphoreCount,			// deUint32						signalSemaphoreCount;
524		pSignalSemaphores,				// const VkSemaphore*			pSignalSemaphores;
525	};
526
527	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, DE_NULL));
528}
529
530void submitCommandsAndWait (const DeviceInterface&		vk,
531							const VkDevice				device,
532							const VkQueue				queue,
533							const VkCommandBuffer		commandBuffer,
534							const deUint32				waitSemaphoreCount,
535							const VkSemaphore*			pWaitSemaphores,
536							const VkPipelineStageFlags*	pWaitDstStageMask,
537							const deUint32				signalSemaphoreCount,
538							const VkSemaphore*			pSignalSemaphores)
539{
540	const VkFenceCreateInfo	fenceParams =
541	{
542		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
543		DE_NULL,								// const void*			pNext;
544		0u,										// VkFenceCreateFlags	flags;
545	};
546	const Unique<VkFence> fence(createFence(vk, device, &fenceParams));
547
548	const VkSubmitInfo submitInfo =
549	{
550		VK_STRUCTURE_TYPE_SUBMIT_INFO,		// VkStructureType				sType;
551		DE_NULL,							// const void*					pNext;
552		waitSemaphoreCount,					// deUint32						waitSemaphoreCount;
553		pWaitSemaphores,					// const VkSemaphore*			pWaitSemaphores;
554		pWaitDstStageMask,					// const VkPipelineStageFlags*	pWaitDstStageMask;
555		1u,									// deUint32						commandBufferCount;
556		&commandBuffer,						// const VkCommandBuffer*		pCommandBuffers;
557		signalSemaphoreCount,				// deUint32						signalSemaphoreCount;
558		pSignalSemaphores,					// const VkSemaphore*			pSignalSemaphores;
559	};
560
561	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
562	VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
563}
564
565VkImageType	mapImageType (const ImageType imageType)
566{
567	switch (imageType)
568	{
569		case IMAGE_TYPE_1D:
570		case IMAGE_TYPE_1D_ARRAY:
571		case IMAGE_TYPE_BUFFER:
572			return VK_IMAGE_TYPE_1D;
573
574		case IMAGE_TYPE_2D:
575		case IMAGE_TYPE_2D_ARRAY:
576		case IMAGE_TYPE_CUBE:
577		case IMAGE_TYPE_CUBE_ARRAY:
578			return VK_IMAGE_TYPE_2D;
579
580		case IMAGE_TYPE_3D:
581			return VK_IMAGE_TYPE_3D;
582
583		default:
584			DE_ASSERT(false);
585			return VK_IMAGE_TYPE_LAST;
586	}
587}
588
589VkImageViewType	mapImageViewType (const ImageType imageType)
590{
591	switch (imageType)
592	{
593		case IMAGE_TYPE_1D:			return VK_IMAGE_VIEW_TYPE_1D;
594		case IMAGE_TYPE_1D_ARRAY:	return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
595		case IMAGE_TYPE_2D:			return VK_IMAGE_VIEW_TYPE_2D;
596		case IMAGE_TYPE_2D_ARRAY:	return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
597		case IMAGE_TYPE_3D:			return VK_IMAGE_VIEW_TYPE_3D;
598		case IMAGE_TYPE_CUBE:		return VK_IMAGE_VIEW_TYPE_CUBE;
599		case IMAGE_TYPE_CUBE_ARRAY:	return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
600
601		default:
602			DE_ASSERT(false);
603			return VK_IMAGE_VIEW_TYPE_LAST;
604	}
605}
606
607std::string getImageTypeName (const ImageType imageType)
608{
609	switch (imageType)
610	{
611		case IMAGE_TYPE_1D:			return "1d";
612		case IMAGE_TYPE_1D_ARRAY:	return "1d_array";
613		case IMAGE_TYPE_2D:			return "2d";
614		case IMAGE_TYPE_2D_ARRAY:	return "2d_array";
615		case IMAGE_TYPE_3D:			return "3d";
616		case IMAGE_TYPE_CUBE:		return "cube";
617		case IMAGE_TYPE_CUBE_ARRAY:	return "cube_array";
618		case IMAGE_TYPE_BUFFER:		return "buffer";
619
620		default:
621			DE_ASSERT(false);
622			return "";
623	}
624}
625
626std::string getShaderImageType (const tcu::TextureFormat& format, const ImageType imageType)
627{
628	std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
629							 tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";
630
631	std::string imageTypePart;
632	switch (imageType)
633	{
634		case IMAGE_TYPE_1D:			imageTypePart = "1D";			break;
635		case IMAGE_TYPE_1D_ARRAY:	imageTypePart = "1DArray";		break;
636		case IMAGE_TYPE_2D:			imageTypePart = "2D";			break;
637		case IMAGE_TYPE_2D_ARRAY:	imageTypePart = "2DArray";		break;
638		case IMAGE_TYPE_3D:			imageTypePart = "3D";			break;
639		case IMAGE_TYPE_CUBE:		imageTypePart = "Cube";			break;
640		case IMAGE_TYPE_CUBE_ARRAY:	imageTypePart = "CubeArray";	break;
641		case IMAGE_TYPE_BUFFER:		imageTypePart = "Buffer";		break;
642
643		default:
644			DE_ASSERT(false);
645	}
646
647	return formatPart + "image" + imageTypePart;
648}
649
650
651std::string getShaderImageDataType(const tcu::TextureFormat& format)
652{
653	switch (tcu::getTextureChannelClass(format.type))
654	{
655		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
656			return "uvec4";
657		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
658			return "ivec4";
659		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
660			return "vec4";
661		default:
662			DE_ASSERT(false);
663			return "";
664	}
665}
666
667
668std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
669{
670	const char* orderPart;
671	const char* typePart;
672
673	switch (format.order)
674	{
675		case tcu::TextureFormat::R:		orderPart = "r";	break;
676		case tcu::TextureFormat::RG:	orderPart = "rg";	break;
677		case tcu::TextureFormat::RGB:	orderPart = "rgb";	break;
678		case tcu::TextureFormat::RGBA:	orderPart = "rgba";	break;
679
680		default:
681			DE_ASSERT(false);
682			orderPart = DE_NULL;
683	}
684
685	switch (format.type)
686	{
687		case tcu::TextureFormat::FLOAT:				typePart = "32f";		break;
688		case tcu::TextureFormat::HALF_FLOAT:		typePart = "16f";		break;
689
690		case tcu::TextureFormat::UNSIGNED_INT32:	typePart = "32ui";		break;
691		case tcu::TextureFormat::UNSIGNED_INT16:	typePart = "16ui";		break;
692		case tcu::TextureFormat::UNSIGNED_INT8:		typePart = "8ui";		break;
693
694		case tcu::TextureFormat::SIGNED_INT32:		typePart = "32i";		break;
695		case tcu::TextureFormat::SIGNED_INT16:		typePart = "16i";		break;
696		case tcu::TextureFormat::SIGNED_INT8:		typePart = "8i";		break;
697
698		case tcu::TextureFormat::UNORM_INT16:		typePart = "16";		break;
699		case tcu::TextureFormat::UNORM_INT8:		typePart = "8";			break;
700
701		case tcu::TextureFormat::SNORM_INT16:		typePart = "16_snorm";	break;
702		case tcu::TextureFormat::SNORM_INT8:		typePart = "8_snorm";	break;
703
704		default:
705			DE_ASSERT(false);
706			typePart = DE_NULL;
707	}
708
709	return std::string() + orderPart + typePart;
710}
711
712std::string getShaderImageCoordinates	(const ImageType	imageType,
713										 const std::string&	x,
714										 const std::string&	xy,
715										 const std::string&	xyz)
716{
717	switch (imageType)
718	{
719		case IMAGE_TYPE_1D:
720		case IMAGE_TYPE_BUFFER:
721			return x;
722
723		case IMAGE_TYPE_1D_ARRAY:
724		case IMAGE_TYPE_2D:
725			return xy;
726
727		case IMAGE_TYPE_2D_ARRAY:
728		case IMAGE_TYPE_3D:
729		case IMAGE_TYPE_CUBE:
730		case IMAGE_TYPE_CUBE_ARRAY:
731			return xyz;
732
733		default:
734			DE_ASSERT(0);
735			return "";
736	}
737}
738
739VkExtent3D mipLevelExtents (const VkExtent3D& baseExtents, const deUint32 mipLevel)
740{
741	VkExtent3D result;
742
743	result.width	= std::max(baseExtents.width  >> mipLevel, 1u);
744	result.height	= std::max(baseExtents.height >> mipLevel, 1u);
745	result.depth	= std::max(baseExtents.depth  >> mipLevel, 1u);
746
747	return result;
748}
749
750deUint32 getImageMaxMipLevels (const VkImageFormatProperties& imageFormatProperties, const VkExtent3D& extent)
751{
752	const deUint32 widestEdge = std::max(std::max(extent.width, extent.height), extent.depth);
753
754	return std::min(static_cast<deUint32>(deFloatLog2(static_cast<float>(widestEdge))) + 1u, imageFormatProperties.maxMipLevels);
755}
756
757deUint32 getImageMipLevelSizeInBytes(const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel, const deUint32 mipmapMemoryAlignment)
758{
759	const VkExtent3D extents = mipLevelExtents(baseExtents, mipmapLevel);
760
761	return deAlign32(extents.width * extents.height * extents.depth * layersCount * tcu::getPixelSize(format), mipmapMemoryAlignment);
762}
763
764deUint32 getImageSizeInBytes(const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount, const deUint32 mipmapMemoryAlignment)
765{
766	deUint32 imageSizeInBytes = 0;
767	for (deUint32 mipmapLevel = 0; mipmapLevel < mipmapLevelsCount; ++mipmapLevel)
768		imageSizeInBytes += getImageMipLevelSizeInBytes(baseExtents, layersCount, format, mipmapLevel, mipmapMemoryAlignment);
769
770	return imageSizeInBytes;
771}
772
773VkSparseImageMemoryBind	makeSparseImageMemoryBind  (const DeviceInterface&			vk,
774													const VkDevice					device,
775													const VkDeviceSize				allocationSize,
776													const deUint32					memoryType,
777													const VkImageSubresource&		subresource,
778													const VkOffset3D&				offset,
779													const VkExtent3D&				extent)
780{
781	const VkMemoryAllocateInfo	allocInfo =
782	{
783		VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,	//	VkStructureType			sType;
784		DE_NULL,								//	const void*				pNext;
785		allocationSize,							//	VkDeviceSize			allocationSize;
786		memoryType,								//	deUint32				memoryTypeIndex;
787	};
788
789	VkDeviceMemory deviceMemory = 0;
790	VK_CHECK(vk.allocateMemory(device, &allocInfo, DE_NULL, &deviceMemory));
791
792	VkSparseImageMemoryBind imageMemoryBind;
793
794	imageMemoryBind.subresource		= subresource;
795	imageMemoryBind.memory			= deviceMemory;
796	imageMemoryBind.memoryOffset	= 0u;
797	imageMemoryBind.flags			= 0u;
798	imageMemoryBind.offset			= offset;
799	imageMemoryBind.extent			= extent;
800
801	return imageMemoryBind;
802}
803
804VkSparseMemoryBind makeSparseMemoryBind	(const DeviceInterface&			vk,
805										 const VkDevice					device,
806										 const VkDeviceSize				allocationSize,
807										 const deUint32					memoryType,
808										 const VkDeviceSize				resourceOffset,
809										 const VkSparseMemoryBindFlags	flags)
810{
811	const VkMemoryAllocateInfo allocInfo =
812	{
813		VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,	//	VkStructureType	sType;
814		DE_NULL,								//	const void*		pNext;
815		allocationSize,							//	VkDeviceSize	allocationSize;
816		memoryType,								//	deUint32		memoryTypeIndex;
817	};
818
819	VkDeviceMemory deviceMemory = 0;
820	VK_CHECK(vk.allocateMemory(device, &allocInfo, DE_NULL, &deviceMemory));
821
822	VkSparseMemoryBind memoryBind;
823
824	memoryBind.resourceOffset	= resourceOffset;
825	memoryBind.size				= allocationSize;
826	memoryBind.memory			= deviceMemory;
827	memoryBind.memoryOffset		= 0u;
828	memoryBind.flags			= flags;
829
830	return memoryBind;
831}
832
833void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
834{
835	const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
836
837	if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
838		throw tcu::NotSupportedError("Tessellation shader not supported");
839
840	if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
841		throw tcu::NotSupportedError("Geometry shader not supported");
842
843	if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
844		throw tcu::NotSupportedError("Double-precision floats not supported");
845
846	if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
847		throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
848
849	if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
850		throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
851
852	if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
853		throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
854}
855
856deUint32 findMatchingMemoryType (const InstanceInterface&		instance,
857								 const VkPhysicalDevice			physicalDevice,
858								 const VkMemoryRequirements&	objectMemoryRequirements,
859								 const MemoryRequirement&		memoryRequirement)
860{
861	const VkPhysicalDeviceMemoryProperties deviceMemoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice);
862
863	for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemoryProperties.memoryTypeCount; ++memoryTypeNdx)
864	{
865		if ((objectMemoryRequirements.memoryTypeBits & (1u << memoryTypeNdx)) != 0 &&
866			memoryRequirement.matchesHeap(deviceMemoryProperties.memoryTypes[memoryTypeNdx].propertyFlags))
867		{
868			return memoryTypeNdx;
869		}
870	}
871
872	return NO_MATCH_FOUND;
873}
874
875bool checkSparseSupportForImageType (const InstanceInterface&	instance,
876									 const VkPhysicalDevice		physicalDevice,
877									 const ImageType			imageType)
878{
879	const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instance, physicalDevice);
880
881	if (!deviceFeatures.sparseBinding)
882		return false;
883
884	switch (mapImageType(imageType))
885	{
886		case VK_IMAGE_TYPE_2D:
887			return deviceFeatures.sparseResidencyImage2D == VK_TRUE;
888		case VK_IMAGE_TYPE_3D:
889			return deviceFeatures.sparseResidencyImage3D == VK_TRUE;
890		default:
891			DE_ASSERT(0);
892			return false;
893	};
894}
895
896bool checkSparseSupportForImageFormat (const InstanceInterface&	instance,
897									   const VkPhysicalDevice	physicalDevice,
898									   const VkImageCreateInfo&	imageInfo)
899{
900	const std::vector<VkSparseImageFormatProperties> sparseImageFormatPropVec = getPhysicalDeviceSparseImageFormatProperties(
901		instance, physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.samples, imageInfo.usage, imageInfo.tiling);
902
903	return sparseImageFormatPropVec.size() > 0u;
904}
905
906bool checkImageFormatFeatureSupport (const InstanceInterface&	instance,
907									 const VkPhysicalDevice		physicalDevice,
908									 const VkFormat				format,
909									 const VkFormatFeatureFlags	featureFlags)
910{
911	const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format);
912
913	return (formatProperties.optimalTilingFeatures & featureFlags) == featureFlags;
914}
915
916deUint32 getSparseAspectRequirementsIndex (const std::vector<VkSparseImageMemoryRequirements>&	requirements,
917										   const VkImageAspectFlags								aspectFlags)
918{
919	for (deUint32 memoryReqNdx = 0; memoryReqNdx < requirements.size(); ++memoryReqNdx)
920	{
921		if (requirements[memoryReqNdx].formatProperties.aspectMask & aspectFlags)
922			return memoryReqNdx;
923	}
924
925	return NO_MATCH_FOUND;
926}
927
928} // sparse
929} // vkt
930