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 "vkApiVersion.hpp"
26
27#include "deMemory.h"
28#include "deString.h"
29#include "deSTLUtil.hpp"
30
31#include <vector>
32
33namespace vk
34{
35
36using std::vector;
37
38namespace
39{
40
41#include "vkSupportedExtensions.inl"
42
43}
44
45void getCoreInstanceExtensions(deUint32 apiVersion, vector<const char*>& dst)
46{
47	getCoreInstanceExtensionsImpl(apiVersion, dst);
48}
49
50void getCoreDeviceExtensions(deUint32 apiVersion, vector<const char*>& dst)
51{
52	getCoreDeviceExtensionsImpl(apiVersion, dst);
53}
54
55bool isCoreInstanceExtension(const deUint32 apiVersion, const std::string& extension)
56{
57	vector<const char*> coreExtensions;
58	getCoreInstanceExtensions(apiVersion, coreExtensions);
59	if (de::contains(coreExtensions.begin(), coreExtensions.end(), extension))
60		return true;
61
62	return false;
63}
64
65bool isCoreDeviceExtension(const deUint32 apiVersion, const std::string& extension)
66{
67	vector<const char*> coreExtensions;
68	getCoreDeviceExtensions(apiVersion, coreExtensions);
69	if (de::contains(coreExtensions.begin(), coreExtensions.end(), extension))
70		return true;
71
72	return false;
73}
74
75vector<VkPhysicalDevice> enumeratePhysicalDevices (const InstanceInterface& vk, VkInstance instance)
76{
77	deUint32					numDevices	= 0;
78	vector<VkPhysicalDevice>	devices;
79
80	VK_CHECK(vk.enumeratePhysicalDevices(instance, &numDevices, DE_NULL));
81
82	if (numDevices > 0)
83	{
84		devices.resize(numDevices);
85		VK_CHECK(vk.enumeratePhysicalDevices(instance, &numDevices, &devices[0]));
86
87		if ((size_t)numDevices != devices.size())
88			TCU_FAIL("Returned device count changed between queries");
89	}
90
91	return devices;
92}
93
94vector<VkPhysicalDeviceGroupProperties> enumeratePhysicalDeviceGroups(const InstanceInterface& vk, VkInstance instance)
95{
96	deUint32								numDeviceGroups = 0;
97	vector<VkPhysicalDeviceGroupProperties>	properties;
98
99	VK_CHECK(vk.enumeratePhysicalDeviceGroups(instance, &numDeviceGroups, DE_NULL));
100
101	if (numDeviceGroups > 0)
102	{
103		properties.resize(numDeviceGroups);
104		for (deUint32 i = 0; i < numDeviceGroups; i++)
105		{
106			properties[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR;
107			properties[i].pNext = DE_NULL;
108		}
109		VK_CHECK(vk.enumeratePhysicalDeviceGroups(instance, &numDeviceGroups, &properties[0]));
110
111		if ((size_t)numDeviceGroups != properties.size())
112			TCU_FAIL("Returned device group count changed between queries");
113	}
114	return properties;
115}
116
117vector<VkQueueFamilyProperties> getPhysicalDeviceQueueFamilyProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
118{
119	deUint32						numQueues	= 0;
120	vector<VkQueueFamilyProperties>	properties;
121
122	vk.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, DE_NULL);
123
124	if (numQueues > 0)
125	{
126		properties.resize(numQueues);
127		vk.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, &properties[0]);
128
129		if ((size_t)numQueues != properties.size())
130			TCU_FAIL("Returned queue family count changes between queries");
131	}
132
133	return properties;
134}
135
136VkPhysicalDeviceFeatures getPhysicalDeviceFeatures (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
137{
138	VkPhysicalDeviceFeatures	features;
139
140	deMemset(&features, 0, sizeof(features));
141
142	vk.getPhysicalDeviceFeatures(physicalDevice, &features);
143	return features;
144}
145
146VkPhysicalDeviceFeatures2 getPhysicalDeviceFeatures2 (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
147{
148	VkPhysicalDeviceFeatures2	features;
149
150	deMemset(&features, 0, sizeof(features));
151	features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
152
153	vk.getPhysicalDeviceFeatures2(physicalDevice, &features);
154	return features;
155}
156
157VkPhysicalDeviceProperties getPhysicalDeviceProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
158{
159	VkPhysicalDeviceProperties	properties;
160
161	deMemset(&properties, 0, sizeof(properties));
162
163	vk.getPhysicalDeviceProperties(physicalDevice, &properties);
164	return properties;
165}
166
167VkPhysicalDeviceMemoryProperties getPhysicalDeviceMemoryProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
168{
169	VkPhysicalDeviceMemoryProperties	properties;
170
171	deMemset(&properties, 0, sizeof(properties));
172
173	vk.getPhysicalDeviceMemoryProperties(physicalDevice, &properties);
174	return properties;
175}
176
177VkFormatProperties getPhysicalDeviceFormatProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format)
178{
179	VkFormatProperties	properties;
180
181	deMemset(&properties, 0, sizeof(properties));
182
183	vk.getPhysicalDeviceFormatProperties(physicalDevice, format, &properties);
184	return properties;
185}
186
187VkImageFormatProperties getPhysicalDeviceImageFormatProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags)
188{
189	VkImageFormatProperties	properties;
190
191	deMemset(&properties, 0, sizeof(properties));
192
193	VK_CHECK(vk.getPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags, &properties));
194	return properties;
195}
196
197std::vector<VkSparseImageFormatProperties> getPhysicalDeviceSparseImageFormatProperties(const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling)
198{
199	deUint32								numProp = 0;
200	vector<VkSparseImageFormatProperties>	properties;
201
202	vk.getPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, &numProp, DE_NULL);
203
204	if (numProp > 0)
205	{
206		properties.resize(numProp);
207		vk.getPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, &numProp, &properties[0]);
208
209		if ((size_t)numProp != properties.size())
210			TCU_FAIL("Returned sparse image properties count changes between queries");
211	}
212
213	return properties;
214}
215
216std::vector<VkSparseImageMemoryRequirements> getImageSparseMemoryRequirements(const DeviceInterface& vk, VkDevice device, VkImage image)
217{
218	deUint32								requirementsCount = 0;
219	vector<VkSparseImageMemoryRequirements> requirements;
220
221	vk.getImageSparseMemoryRequirements(device, image, &requirementsCount, DE_NULL);
222
223	if (requirementsCount > 0)
224	{
225		requirements.resize(requirementsCount);
226		vk.getImageSparseMemoryRequirements(device, image, &requirementsCount, &requirements[0]);
227
228		if ((size_t)requirementsCount != requirements.size())
229			TCU_FAIL("Returned sparse image memory requirements count changes between queries");
230	}
231
232	return requirements;
233}
234
235VkMemoryRequirements getBufferMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkBuffer buffer)
236{
237	VkMemoryRequirements req;
238	vk.getBufferMemoryRequirements(device, buffer, &req);
239	return req;
240}
241
242VkMemoryRequirements getImageMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkImage image)
243{
244	VkMemoryRequirements req;
245	vk.getImageMemoryRequirements(device, image, &req);
246	return req;
247}
248
249VkMemoryRequirements getImagePlaneMemoryRequirements (const DeviceInterface&	vkd,
250													  VkDevice					device,
251													  VkImage					image,
252													  VkImageAspectFlagBits		planeAspect)
253{
254	VkImageMemoryRequirementsInfo2		coreInfo;
255	VkImagePlaneMemoryRequirementsInfo	planeInfo;
256	VkMemoryRequirements2				reqs;
257
258	deMemset(&coreInfo,		0, sizeof(coreInfo));
259	deMemset(&planeInfo,	0, sizeof(planeInfo));
260	deMemset(&reqs,			0, sizeof(reqs));
261
262	coreInfo.sType			= VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR;
263	coreInfo.pNext			= &planeInfo;
264	coreInfo.image			= image;
265
266	planeInfo.sType			= VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR;
267	planeInfo.planeAspect	= planeAspect;
268
269	reqs.sType				= VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR;
270
271	vkd.getImageMemoryRequirements2(device, &coreInfo, &reqs);
272
273	return reqs.memoryRequirements;
274}
275
276vector<VkLayerProperties> enumerateInstanceLayerProperties (const PlatformInterface& vkp)
277{
278	vector<VkLayerProperties>	properties;
279	deUint32					numLayers	= 0;
280
281	VK_CHECK(vkp.enumerateInstanceLayerProperties(&numLayers, DE_NULL));
282
283	if (numLayers > 0)
284	{
285		properties.resize(numLayers);
286		VK_CHECK(vkp.enumerateInstanceLayerProperties(&numLayers, &properties[0]));
287		TCU_CHECK((size_t)numLayers == properties.size());
288	}
289
290	return properties;
291}
292
293vector<VkExtensionProperties> enumerateInstanceExtensionProperties (const PlatformInterface& vkp, const char* layerName)
294{
295	vector<VkExtensionProperties>	properties;
296	deUint32						numExtensions	= 0;
297
298	VK_CHECK(vkp.enumerateInstanceExtensionProperties(layerName, &numExtensions, DE_NULL));
299
300	if (numExtensions > 0)
301	{
302		properties.resize(numExtensions);
303		VK_CHECK(vkp.enumerateInstanceExtensionProperties(layerName, &numExtensions, &properties[0]));
304		TCU_CHECK((size_t)numExtensions == properties.size());
305	}
306
307	return properties;
308}
309
310vector<VkLayerProperties> enumerateDeviceLayerProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
311{
312	vector<VkLayerProperties>	properties;
313	deUint32					numLayers	= 0;
314
315	VK_CHECK(vki.enumerateDeviceLayerProperties(physicalDevice, &numLayers, DE_NULL));
316
317	if (numLayers > 0)
318	{
319		properties.resize(numLayers);
320		VK_CHECK(vki.enumerateDeviceLayerProperties(physicalDevice, &numLayers, &properties[0]));
321		TCU_CHECK((size_t)numLayers == properties.size());
322	}
323
324	return properties;
325}
326
327vector<VkExtensionProperties> enumerateDeviceExtensionProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, const char* layerName)
328{
329	vector<VkExtensionProperties>	properties;
330	deUint32						numExtensions	= 0;
331
332	VK_CHECK(vki.enumerateDeviceExtensionProperties(physicalDevice, layerName, &numExtensions, DE_NULL));
333
334	if (numExtensions > 0)
335	{
336		properties.resize(numExtensions);
337		VK_CHECK(vki.enumerateDeviceExtensionProperties(physicalDevice, layerName, &numExtensions, &properties[0]));
338		TCU_CHECK((size_t)numExtensions == properties.size());
339	}
340
341	return properties;
342}
343
344bool isShaderStageSupported (const VkPhysicalDeviceFeatures& deviceFeatures, VkShaderStageFlagBits stage)
345{
346	if (stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
347		return deviceFeatures.tessellationShader == VK_TRUE;
348	else if (stage == VK_SHADER_STAGE_GEOMETRY_BIT)
349		return deviceFeatures.geometryShader == VK_TRUE;
350	else
351		return true;
352}
353
354bool isCompatible (const VkExtensionProperties& extensionProperties, const RequiredExtension& required)
355{
356	if (required.name != extensionProperties.extensionName)
357		return false;
358
359	if (required.minVersion && required.minVersion.get() > extensionProperties.specVersion)
360		return false;
361
362	if (required.maxVersion && required.maxVersion.get() < extensionProperties.specVersion)
363		return false;
364
365	return true;
366}
367
368bool isCompatible (const VkLayerProperties& layerProperties, const RequiredLayer& required)
369{
370	if (required.name != layerProperties.layerName)
371		return false;
372
373	if (required.minSpecVersion && required.minSpecVersion.get() > layerProperties.specVersion)
374		return false;
375
376	if (required.maxSpecVersion && required.maxSpecVersion.get() < layerProperties.specVersion)
377		return false;
378
379	if (required.minImplVersion && required.minImplVersion.get() > layerProperties.implementationVersion)
380		return false;
381
382	if (required.maxImplVersion && required.maxImplVersion.get() < layerProperties.implementationVersion)
383		return false;
384
385	return true;
386}
387
388bool isInstanceExtensionSupported (const deUint32 instanceVersion, const std::vector<std::string>& extensions, const std::string& required)
389{
390	if (isCoreInstanceExtension(instanceVersion, required))
391		return true;
392	else
393		return de::contains(extensions.begin(), extensions.end(), required);
394}
395
396bool isDeviceExtensionSupported (const deUint32 deviceVersion, const std::vector<std::string>& extensions, const std::string& required)
397{
398	if (isCoreDeviceExtension(deviceVersion, required))
399		return true;
400	else
401		return de::contains(extensions.begin(), extensions.end(), required);
402}
403
404bool isInstanceExtensionSupported (const deUint32 instanceVersion, const std::vector<VkExtensionProperties>& extensions, const RequiredExtension& required)
405{
406	if (isCoreInstanceExtension(instanceVersion, required.name))
407		return true;
408	else
409		return isExtensionSupported(extensions.begin(), extensions.end(), required);
410}
411
412bool isDeviceExtensionSupported (const deUint32 deviceVersion, const std::vector<VkExtensionProperties>& extensions, const RequiredExtension& required)
413{
414	if (isCoreDeviceExtension(deviceVersion, required.name))
415		return true;
416	else
417		return isExtensionSupported(extensions.begin(), extensions.end(), required);
418}
419
420bool isExtensionSupported (const std::vector<VkExtensionProperties>& extensions, const RequiredExtension& required)
421{
422	return isExtensionSupported(extensions.begin(), extensions.end(), required);
423}
424
425bool isLayerSupported (const std::vector<VkLayerProperties>& layers, const RequiredLayer& required)
426{
427	return isLayerSupported(layers.begin(), layers.end(), required);
428}
429
430VkQueue getDeviceQueue (const DeviceInterface& vkd, VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex)
431{
432	VkQueue queue;
433
434	vkd.getDeviceQueue(device, queueFamilyIndex, queueIndex, &queue);
435
436	return queue;
437}
438
439VkQueue getDeviceQueue2 (const DeviceInterface& vkd, VkDevice device, const VkDeviceQueueInfo2* queueInfo)
440{
441	VkQueue queue;
442
443	vkd.getDeviceQueue2(device, queueInfo, &queue);
444
445	return queue;
446}
447
448const void* findStructureInChain (const void* first, VkStructureType type)
449{
450	struct StructureBase
451	{
452		VkStructureType		sType;
453		void*				pNext;
454	};
455
456	const StructureBase*	cur		= reinterpret_cast<const StructureBase*>(first);
457
458	while (cur)
459	{
460		if (cur->sType == type)
461			break;
462		else
463			cur = reinterpret_cast<const StructureBase*>(cur->pNext);
464	}
465
466	return cur;
467}
468
469void* findStructureInChain (void* first, VkStructureType type)
470{
471	return const_cast<void*>(findStructureInChain(const_cast<const void*>(first), type));
472}
473
474// getStructureType<T> implementations
475#include "vkGetStructureTypeImpl.inl"
476
477} // vk
478