1/*-------------------------------------------------------------------------
2 * Vulkan CTS Framework
3 * --------------------
4 *
5 * Copyright (c) 2015 Google 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 Vulkan query utilities.
22 *//*--------------------------------------------------------------------*/
23
24#include "vkQueryUtil.hpp"
25#include "deMemory.h"
26
27namespace vk
28{
29
30using std::vector;
31
32vector<VkPhysicalDevice> enumeratePhysicalDevices (const InstanceInterface& vk, VkInstance instance)
33{
34	deUint32					numDevices	= 0;
35	vector<VkPhysicalDevice>	devices;
36
37	VK_CHECK(vk.enumeratePhysicalDevices(instance, &numDevices, DE_NULL));
38
39	if (numDevices > 0)
40	{
41		devices.resize(numDevices);
42		VK_CHECK(vk.enumeratePhysicalDevices(instance, &numDevices, &devices[0]));
43
44		if ((size_t)numDevices != devices.size())
45			TCU_FAIL("Returned device count changed between queries");
46	}
47
48	return devices;
49}
50
51vector<VkQueueFamilyProperties> getPhysicalDeviceQueueFamilyProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
52{
53	deUint32						numQueues	= 0;
54	vector<VkQueueFamilyProperties>	properties;
55
56	vk.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, DE_NULL);
57
58	if (numQueues > 0)
59	{
60		properties.resize(numQueues);
61		vk.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, &properties[0]);
62
63		if ((size_t)numQueues != properties.size())
64			TCU_FAIL("Returned queue family count changes between queries");
65	}
66
67	return properties;
68}
69
70VkPhysicalDeviceFeatures getPhysicalDeviceFeatures (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
71{
72	VkPhysicalDeviceFeatures	features;
73
74	deMemset(&features, 0, sizeof(features));
75
76	vk.getPhysicalDeviceFeatures(physicalDevice, &features);
77	return features;
78}
79
80VkPhysicalDeviceProperties getPhysicalDeviceProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
81{
82	VkPhysicalDeviceProperties	properties;
83
84	deMemset(&properties, 0, sizeof(properties));
85
86	vk.getPhysicalDeviceProperties(physicalDevice, &properties);
87	return properties;
88}
89
90VkPhysicalDeviceMemoryProperties getPhysicalDeviceMemoryProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
91{
92	VkPhysicalDeviceMemoryProperties	properties;
93
94	deMemset(&properties, 0, sizeof(properties));
95
96	vk.getPhysicalDeviceMemoryProperties(physicalDevice, &properties);
97	return properties;
98}
99
100VkFormatProperties getPhysicalDeviceFormatProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format)
101{
102	VkFormatProperties	properties;
103
104	deMemset(&properties, 0, sizeof(properties));
105
106	vk.getPhysicalDeviceFormatProperties(physicalDevice, format, &properties);
107	return properties;
108}
109
110VkImageFormatProperties getPhysicalDeviceImageFormatProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags)
111{
112	VkImageFormatProperties	properties;
113
114	deMemset(&properties, 0, sizeof(properties));
115
116	VK_CHECK(vk.getPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags, &properties));
117	return properties;
118}
119
120std::vector<VkSparseImageFormatProperties> getPhysicalDeviceSparseImageFormatProperties(const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling)
121{
122	deUint32								numProp = 0;
123	vector<VkSparseImageFormatProperties>	properties;
124
125	vk.getPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, &numProp, DE_NULL);
126
127	if (numProp > 0)
128	{
129		properties.resize(numProp);
130		vk.getPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, &numProp, &properties[0]);
131
132		if ((size_t)numProp != properties.size())
133			TCU_FAIL("Returned sparse image properties count changes between queries");
134	}
135
136	return properties;
137}
138
139std::vector<VkSparseImageMemoryRequirements> getImageSparseMemoryRequirements(const DeviceInterface& vk, VkDevice device, VkImage image)
140{
141	deUint32								requirementsCount = 0;
142	vector<VkSparseImageMemoryRequirements> requirements;
143
144	vk.getImageSparseMemoryRequirements(device, image, &requirementsCount, DE_NULL);
145
146	if (requirementsCount > 0)
147	{
148		requirements.resize(requirementsCount);
149		vk.getImageSparseMemoryRequirements(device, image, &requirementsCount, &requirements[0]);
150
151		if ((size_t)requirementsCount != requirements.size())
152			TCU_FAIL("Returned sparse image memory requirements count changes between queries");
153	}
154
155	return requirements;
156}
157
158VkMemoryRequirements getBufferMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkBuffer buffer)
159{
160	VkMemoryRequirements req;
161	vk.getBufferMemoryRequirements(device, buffer, &req);
162	return req;
163}
164
165VkMemoryRequirements getImageMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkImage image)
166{
167	VkMemoryRequirements req;
168	vk.getImageMemoryRequirements(device, image, &req);
169	return req;
170}
171
172VkMemoryRequirements getImagePlaneMemoryRequirements (const DeviceInterface&	vkd,
173													  VkDevice					device,
174													  VkImage					image,
175													  VkImageAspectFlagBits		planeAspect)
176{
177	VkImageMemoryRequirementsInfo2KHR		coreInfo;
178	VkImagePlaneMemoryRequirementsInfoKHR	planeInfo;
179	VkMemoryRequirements2KHR				reqs;
180
181	deMemset(&coreInfo,		0, sizeof(coreInfo));
182	deMemset(&planeInfo,	0, sizeof(planeInfo));
183	deMemset(&reqs,			0, sizeof(reqs));
184
185	coreInfo.sType			= VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR;
186	coreInfo.pNext			= &planeInfo;
187	coreInfo.image			= image;
188
189	planeInfo.sType			= VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR;
190	planeInfo.planeAspect	= planeAspect;
191
192	reqs.sType				= VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR;
193
194	vkd.getImageMemoryRequirements2KHR(device, &coreInfo, &reqs);
195
196	return reqs.memoryRequirements;
197}
198
199vector<VkLayerProperties> enumerateInstanceLayerProperties (const PlatformInterface& vkp)
200{
201	vector<VkLayerProperties>	properties;
202	deUint32					numLayers	= 0;
203
204	VK_CHECK(vkp.enumerateInstanceLayerProperties(&numLayers, DE_NULL));
205
206	if (numLayers > 0)
207	{
208		properties.resize(numLayers);
209		VK_CHECK(vkp.enumerateInstanceLayerProperties(&numLayers, &properties[0]));
210		TCU_CHECK((size_t)numLayers == properties.size());
211	}
212
213	return properties;
214}
215
216vector<VkExtensionProperties> enumerateInstanceExtensionProperties (const PlatformInterface& vkp, const char* layerName)
217{
218	vector<VkExtensionProperties>	properties;
219	deUint32						numExtensions	= 0;
220
221	VK_CHECK(vkp.enumerateInstanceExtensionProperties(layerName, &numExtensions, DE_NULL));
222
223	if (numExtensions > 0)
224	{
225		properties.resize(numExtensions);
226		VK_CHECK(vkp.enumerateInstanceExtensionProperties(layerName, &numExtensions, &properties[0]));
227		TCU_CHECK((size_t)numExtensions == properties.size());
228	}
229
230	return properties;
231}
232
233vector<VkLayerProperties> enumerateDeviceLayerProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
234{
235	vector<VkLayerProperties>	properties;
236	deUint32					numLayers	= 0;
237
238	VK_CHECK(vki.enumerateDeviceLayerProperties(physicalDevice, &numLayers, DE_NULL));
239
240	if (numLayers > 0)
241	{
242		properties.resize(numLayers);
243		VK_CHECK(vki.enumerateDeviceLayerProperties(physicalDevice, &numLayers, &properties[0]));
244		TCU_CHECK((size_t)numLayers == properties.size());
245	}
246
247	return properties;
248}
249
250vector<VkExtensionProperties> enumerateDeviceExtensionProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, const char* layerName)
251{
252	vector<VkExtensionProperties>	properties;
253	deUint32						numExtensions	= 0;
254
255	VK_CHECK(vki.enumerateDeviceExtensionProperties(physicalDevice, layerName, &numExtensions, DE_NULL));
256
257	if (numExtensions > 0)
258	{
259		properties.resize(numExtensions);
260		VK_CHECK(vki.enumerateDeviceExtensionProperties(physicalDevice, layerName, &numExtensions, &properties[0]));
261		TCU_CHECK((size_t)numExtensions == properties.size());
262	}
263
264	return properties;
265}
266
267bool isShaderStageSupported (const VkPhysicalDeviceFeatures& deviceFeatures, VkShaderStageFlagBits stage)
268{
269	if (stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
270		return deviceFeatures.tessellationShader == VK_TRUE;
271	else if (stage == VK_SHADER_STAGE_GEOMETRY_BIT)
272		return deviceFeatures.geometryShader == VK_TRUE;
273	else
274		return true;
275}
276
277bool isCompatible (const VkExtensionProperties& extensionProperties, const RequiredExtension& required)
278{
279	if (required.name != extensionProperties.extensionName)
280		return false;
281
282	if (required.minVersion && required.minVersion.get() > extensionProperties.specVersion)
283		return false;
284
285	if (required.maxVersion && required.maxVersion.get() < extensionProperties.specVersion)
286		return false;
287
288	return true;
289}
290
291bool isCompatible (const VkLayerProperties& layerProperties, const RequiredLayer& required)
292{
293	if (required.name != layerProperties.layerName)
294		return false;
295
296	if (required.minSpecVersion && required.minSpecVersion.get() > layerProperties.specVersion)
297		return false;
298
299	if (required.maxSpecVersion && required.maxSpecVersion.get() < layerProperties.specVersion)
300		return false;
301
302	if (required.minImplVersion && required.minImplVersion.get() > layerProperties.implementationVersion)
303		return false;
304
305	if (required.maxImplVersion && required.maxImplVersion.get() < layerProperties.implementationVersion)
306		return false;
307
308	return true;
309}
310
311bool isExtensionSupported (const std::vector<VkExtensionProperties>& extensions, const RequiredExtension& required)
312{
313	return isExtensionSupported(extensions.begin(), extensions.end(), required);
314}
315
316bool isLayerSupported (const std::vector<VkLayerProperties>& layers, const RequiredLayer& required)
317{
318	return isLayerSupported(layers.begin(), layers.end(), required);
319}
320
321VkQueue getDeviceQueue (const DeviceInterface& vkd, VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex)
322{
323	VkQueue queue;
324
325	vkd.getDeviceQueue(device, queueFamilyIndex, queueIndex, &queue);
326
327	return queue;
328}
329
330const void* findStructureInChain (const void* first, VkStructureType type)
331{
332	struct StructureBase
333	{
334		VkStructureType		sType;
335		void*				pNext;
336	};
337
338	const StructureBase*	cur		= reinterpret_cast<const StructureBase*>(first);
339
340	while (cur)
341	{
342		if (cur->sType == type)
343			break;
344		else
345			cur = reinterpret_cast<const StructureBase*>(cur->pNext);
346	}
347
348	return cur;
349}
350
351void* findStructureInChain (void* first, VkStructureType type)
352{
353	return const_cast<void*>(findStructureInChain(const_cast<const void*>(first), type));
354}
355
356// getStructureType<T> implementations
357#include "vkGetStructureTypeImpl.inl"
358
359} // vk
360