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 #include <sstream>
33 #include <memory>
34 #include <map>
35 
36 namespace vk
37 {
38 
39 using std::vector;
40 
41 namespace
42 {
43 
44 #include "vkSupportedExtensions.inl"
45 
46 }
47 
getCoreInstanceExtensions(deUint32 apiVersion, vector<const char*>& dst)48 void getCoreInstanceExtensions(deUint32 apiVersion, vector<const char*>& dst)
49 {
50 	getCoreInstanceExtensionsImpl(apiVersion, dst);
51 }
52 
getCoreDeviceExtensions(deUint32 apiVersion, vector<const char*>& dst)53 void getCoreDeviceExtensions(deUint32 apiVersion, vector<const char*>& dst)
54 {
55 	getCoreDeviceExtensionsImpl(apiVersion, dst);
56 }
57 
isCoreInstanceExtension(const deUint32 apiVersion, const std::string& extension)58 bool isCoreInstanceExtension(const deUint32 apiVersion, const std::string& extension)
59 {
60 	vector<const char*> coreExtensions;
61 	getCoreInstanceExtensions(apiVersion, coreExtensions);
62 	if (de::contains(coreExtensions.begin(), coreExtensions.end(), extension))
63 		return true;
64 
65 	return false;
66 }
67 
isCoreDeviceExtension(const deUint32 apiVersion, const std::string& extension)68 bool isCoreDeviceExtension(const deUint32 apiVersion, const std::string& extension)
69 {
70 	vector<const char*> coreExtensions;
71 	getCoreDeviceExtensions(apiVersion, coreExtensions);
72 	if (de::contains(coreExtensions.begin(), coreExtensions.end(), extension))
73 		return true;
74 
75 	return false;
76 }
77 
enumeratePhysicalDevices(const InstanceInterface& vk, VkInstance instance)78 vector<VkPhysicalDevice> enumeratePhysicalDevices (const InstanceInterface& vk, VkInstance instance)
79 {
80 	deUint32					numDevices	= 0;
81 	vector<VkPhysicalDevice>	devices;
82 
83 	VK_CHECK(vk.enumeratePhysicalDevices(instance, &numDevices, DE_NULL));
84 
85 	if (numDevices > 0)
86 	{
87 		devices.resize(numDevices);
88 		VK_CHECK(vk.enumeratePhysicalDevices(instance, &numDevices, &devices[0]));
89 
90 		if ((size_t)numDevices != devices.size())
91 			TCU_FAIL("Returned device count changed between queries");
92 	}
93 
94 	return devices;
95 }
96 
enumeratePhysicalDeviceGroups(const InstanceInterface& vk, VkInstance instance)97 vector<VkPhysicalDeviceGroupProperties> enumeratePhysicalDeviceGroups(const InstanceInterface& vk, VkInstance instance)
98 {
99 	deUint32								numDeviceGroups = 0;
100 	vector<VkPhysicalDeviceGroupProperties>	properties;
101 
102 	VK_CHECK(vk.enumeratePhysicalDeviceGroups(instance, &numDeviceGroups, DE_NULL));
103 
104 	if (numDeviceGroups > 0)
105 	{
106 		properties.resize(numDeviceGroups, initVulkanStructure());
107 		VK_CHECK(vk.enumeratePhysicalDeviceGroups(instance, &numDeviceGroups, &properties[0]));
108 
109 		if ((size_t)numDeviceGroups != properties.size())
110 			TCU_FAIL("Returned device group count changed between queries");
111 	}
112 	return properties;
113 }
114 
getPhysicalDeviceQueueFamilyProperties(const InstanceInterface& vk, VkPhysicalDevice physicalDevice)115 vector<VkQueueFamilyProperties> getPhysicalDeviceQueueFamilyProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
116 {
117 	deUint32						numQueues	= 0;
118 	vector<VkQueueFamilyProperties>	properties;
119 
120 	vk.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, DE_NULL);
121 
122 	if (numQueues > 0)
123 	{
124 		properties.resize(numQueues);
125 		vk.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, &properties[0]);
126 
127 		if ((size_t)numQueues != properties.size())
128 			TCU_FAIL("Returned queue family count changes between queries");
129 	}
130 
131 	return properties;
132 }
133 
getPhysicalDeviceFeatures(const InstanceInterface& vk, VkPhysicalDevice physicalDevice)134 VkPhysicalDeviceFeatures getPhysicalDeviceFeatures (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
135 {
136 	VkPhysicalDeviceFeatures	features;
137 
138 	deMemset(&features, 0, sizeof(features));
139 
140 	vk.getPhysicalDeviceFeatures(physicalDevice, &features);
141 	return features;
142 }
143 
getPhysicalDeviceFeatures2(const InstanceInterface& vk, VkPhysicalDevice physicalDevice)144 VkPhysicalDeviceFeatures2 getPhysicalDeviceFeatures2 (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
145 {
146 	VkPhysicalDeviceFeatures2	features;
147 
148 	deMemset(&features, 0, sizeof(features));
149 	features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
150 
151 	vk.getPhysicalDeviceFeatures2(physicalDevice, &features);
152 	return features;
153 }
154 
getPhysicalDeviceVulkan11Features(const InstanceInterface& vk, VkPhysicalDevice physicalDevice)155 VkPhysicalDeviceVulkan11Features getPhysicalDeviceVulkan11Features (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
156 {
157 	VkPhysicalDeviceFeatures2			features;
158 	VkPhysicalDeviceVulkan11Features	vulkan_11_features;
159 
160 	deMemset(&features, 0, sizeof(features));
161 	features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
162 
163 	deMemset(&vulkan_11_features, 0, sizeof(vulkan_11_features));
164 	vulkan_11_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
165 
166 	features.pNext = &vulkan_11_features;
167 
168 	vk.getPhysicalDeviceFeatures2(physicalDevice, &features);
169 	return vulkan_11_features;
170 }
171 
getPhysicalDeviceVulkan12Features(const InstanceInterface& vk, VkPhysicalDevice physicalDevice)172 VkPhysicalDeviceVulkan12Features getPhysicalDeviceVulkan12Features (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
173 {
174 	VkPhysicalDeviceFeatures2			features;
175 	VkPhysicalDeviceVulkan12Features	vulkan_12_features;
176 
177 	deMemset(&features, 0, sizeof(features));
178 	features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
179 
180 	deMemset(&vulkan_12_features, 0, sizeof(vulkan_12_features));
181 	vulkan_12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
182 
183 	features.pNext = &vulkan_12_features;
184 
185 	vk.getPhysicalDeviceFeatures2(physicalDevice, &features);
186 	return vulkan_12_features;
187 }
188 
getPhysicalDeviceVulkan11Properties(const InstanceInterface& vk, VkPhysicalDevice physicalDevice)189 VkPhysicalDeviceVulkan11Properties getPhysicalDeviceVulkan11Properties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
190 {
191 	VkPhysicalDeviceVulkan11Properties	vulkan11properties	= initVulkanStructure();
192 	VkPhysicalDeviceProperties2			properties			= initVulkanStructure(&vulkan11properties);
193 
194 	vk.getPhysicalDeviceProperties2(physicalDevice, &properties);
195 
196 	return vulkan11properties;
197 }
198 
getPhysicalDeviceVulkan12Properties(const InstanceInterface& vk, VkPhysicalDevice physicalDevice)199 VkPhysicalDeviceVulkan12Properties getPhysicalDeviceVulkan12Properties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
200 {
201 	VkPhysicalDeviceVulkan12Properties	vulkan12properties	= initVulkanStructure();
202 	VkPhysicalDeviceProperties2			properties			= initVulkanStructure(&vulkan12properties);
203 
204 	vk.getPhysicalDeviceProperties2(physicalDevice, &properties);
205 
206 	return vulkan12properties;
207 }
208 
209 #ifdef CTS_USES_VULKANSC
getPhysicalDeviceVulkanSC10Features(const InstanceInterface& vk, VkPhysicalDevice physicalDevice)210 VkPhysicalDeviceVulkanSC10Features getPhysicalDeviceVulkanSC10Features (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
211 {
212 	VkPhysicalDeviceFeatures2			features;
213 	VkPhysicalDeviceVulkanSC10Features	vulkanSC10Features;
214 
215 	deMemset(&features, 0, sizeof(features));
216 	features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
217 
218 	deMemset(&vulkanSC10Features, 0, sizeof(vulkanSC10Features));
219 	vulkanSC10Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_SC_1_0_FEATURES;
220 
221 	features.pNext = &vulkanSC10Features;
222 
223 	vk.getPhysicalDeviceFeatures2(physicalDevice, &features);
224 	return vulkanSC10Features;
225 }
226 
getPhysicalDeviceVulkanSC10Properties(const InstanceInterface& vk, VkPhysicalDevice physicalDevice)227 VkPhysicalDeviceVulkanSC10Properties getPhysicalDeviceVulkanSC10Properties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
228 {
229 	VkPhysicalDeviceVulkanSC10Properties	vulkanSC10properties	= initVulkanStructure();
230 	VkPhysicalDeviceProperties2				properties				= initVulkanStructure(&vulkanSC10properties);
231 
232 	vk.getPhysicalDeviceProperties2(physicalDevice, &properties);
233 
234 	return vulkanSC10properties;
235 }
236 #endif // CTS_USES_VULKANSC
237 
getPhysicalDeviceProperties(const InstanceInterface& vk, VkPhysicalDevice physicalDevice)238 VkPhysicalDeviceProperties getPhysicalDeviceProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
239 {
240 	VkPhysicalDeviceProperties	properties;
241 
242 	deMemset(&properties, 0, sizeof(properties));
243 
244 	vk.getPhysicalDeviceProperties(physicalDevice, &properties);
245 	return properties;
246 }
247 
getPhysicalDeviceMemoryProperties(const InstanceInterface& vk, VkPhysicalDevice physicalDevice)248 VkPhysicalDeviceMemoryProperties getPhysicalDeviceMemoryProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice)
249 {
250 	VkPhysicalDeviceMemoryProperties	properties;
251 
252 	deMemset(&properties, 0, sizeof(properties));
253 
254 	vk.getPhysicalDeviceMemoryProperties(physicalDevice, &properties);
255 
256 	if (properties.memoryTypeCount > VK_MAX_MEMORY_TYPES)
257 	{
258 		std::ostringstream msg;
259 		msg << "Invalid memoryTypeCount in VkPhysicalDeviceMemoryProperties (got " << properties.memoryTypeCount
260 			<< ", max " << VK_MAX_MEMORY_TYPES << ")";
261 		TCU_FAIL(msg.str());
262 	}
263 
264 	if (properties.memoryHeapCount > VK_MAX_MEMORY_HEAPS)
265 	{
266 		std::ostringstream msg;
267 		msg << "Invalid memoryHeapCount in VkPhysicalDeviceMemoryProperties (got " << properties.memoryHeapCount
268 			<< ", max " << VK_MAX_MEMORY_HEAPS << ")";
269 		TCU_FAIL(msg.str());
270 	}
271 
272 	return properties;
273 }
274 
getPhysicalDeviceFormatProperties(const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format)275 VkFormatProperties getPhysicalDeviceFormatProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format)
276 {
277 	VkFormatProperties	properties;
278 
279 	deMemset(&properties, 0, sizeof(properties));
280 
281 	vk.getPhysicalDeviceFormatProperties(physicalDevice, format, &properties);
282 	return properties;
283 }
284 
getPhysicalDeviceImageFormatProperties(const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags)285 VkImageFormatProperties getPhysicalDeviceImageFormatProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags)
286 {
287 	VkImageFormatProperties	properties;
288 
289 	deMemset(&properties, 0, sizeof(properties));
290 
291 	VK_CHECK(vk.getPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags, &properties));
292 	return properties;
293 }
294 
295 #ifndef CTS_USES_VULKANSC
getPhysicalDeviceSparseImageFormatProperties(const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling)296 std::vector<VkSparseImageFormatProperties> getPhysicalDeviceSparseImageFormatProperties(const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling)
297 {
298 	deUint32								numProp = 0;
299 	vector<VkSparseImageFormatProperties>	properties;
300 
301 	vk.getPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, &numProp, DE_NULL);
302 
303 	if (numProp > 0)
304 	{
305 		properties.resize(numProp);
306 		vk.getPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, &numProp, &properties[0]);
307 
308 		if ((size_t)numProp != properties.size())
309 			TCU_FAIL("Returned sparse image properties count changes between queries");
310 	}
311 
312 	return properties;
313 }
314 
getImageSparseMemoryRequirements(const DeviceInterface& vk, VkDevice device, VkImage image)315 std::vector<VkSparseImageMemoryRequirements> getImageSparseMemoryRequirements(const DeviceInterface& vk, VkDevice device, VkImage image)
316 {
317 	deUint32								requirementsCount = 0;
318 	vector<VkSparseImageMemoryRequirements> requirements;
319 
320 	vk.getImageSparseMemoryRequirements(device, image, &requirementsCount, DE_NULL);
321 
322 	if (requirementsCount > 0)
323 	{
324 		requirements.resize(requirementsCount);
325 		vk.getImageSparseMemoryRequirements(device, image, &requirementsCount, &requirements[0]);
326 
327 		if ((size_t)requirementsCount != requirements.size())
328 			TCU_FAIL("Returned sparse image memory requirements count changes between queries");
329 	}
330 
331 	return requirements;
332 }
333 
getDeviceImageSparseMemoryRequirements(const DeviceInterface& vk, VkDevice device, const VkImageCreateInfo& imageCreateInfo, VkImageAspectFlagBits planeAspect)334 std::vector<vk::VkSparseImageMemoryRequirements>	getDeviceImageSparseMemoryRequirements	(const DeviceInterface&		vk,
335 																							 VkDevice					device,
336 																							 const VkImageCreateInfo&	imageCreateInfo,
337 																							 VkImageAspectFlagBits		planeAspect)
338 {
339 	const VkDeviceImageMemoryRequirements				info
340 	{
341 		VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS,
342 		nullptr,
343 		&imageCreateInfo,
344 		planeAspect
345 	};
346 	std::vector<vk::VkSparseImageMemoryRequirements2>	requirements;
347 	deUint32											count = 0;
348 
349 	vk.getDeviceImageSparseMemoryRequirements(device, &info, &count, DE_NULL);
350 
351 	if (count > 0)
352 	{
353 		requirements.resize(count);
354 		for (deUint32 i = 0; i < count; ++i)
355 			requirements[i] = vk::initVulkanStructure();
356 		vk.getDeviceImageSparseMemoryRequirements(device, &info, &count, requirements.data());
357 
358 		if ((size_t)count != requirements.size())
359 			TCU_FAIL("Returned sparse image memory requirements count changes between queries");
360 	}
361 
362 	std::vector<vk::VkSparseImageMemoryRequirements>	result(requirements.size());
363 	std::transform(requirements.begin(), requirements.end(), result.begin(),
364 		[](const VkSparseImageMemoryRequirements2& item) { return item.memoryRequirements; });
365 
366 	return result;
367 }
368 #endif // CTS_USES_VULKANSC
369 
getBufferMemoryRequirements(const DeviceInterface& vk, VkDevice device, VkBuffer buffer)370 VkMemoryRequirements getBufferMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkBuffer buffer)
371 {
372 	VkMemoryRequirements req;
373 	vk.getBufferMemoryRequirements(device, buffer, &req);
374 	return req;
375 }
376 
getImageMemoryRequirements(const DeviceInterface& vk, VkDevice device, VkImage image)377 VkMemoryRequirements getImageMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkImage image)
378 {
379 	VkMemoryRequirements req;
380 	vk.getImageMemoryRequirements(device, image, &req);
381 	return req;
382 }
383 
getImagePlaneMemoryRequirements(const DeviceInterface& vkd, VkDevice device, VkImage image, VkImageAspectFlagBits planeAspect)384 VkMemoryRequirements getImagePlaneMemoryRequirements (const DeviceInterface&	vkd,
385 													  VkDevice					device,
386 													  VkImage					image,
387 													  VkImageAspectFlagBits		planeAspect)
388 {
389 	VkImageMemoryRequirementsInfo2		coreInfo;
390 	VkImagePlaneMemoryRequirementsInfo	planeInfo;
391 	VkMemoryRequirements2				reqs;
392 
393 	deMemset(&coreInfo,		0, sizeof(coreInfo));
394 	deMemset(&planeInfo,	0, sizeof(planeInfo));
395 	deMemset(&reqs,			0, sizeof(reqs));
396 
397 	coreInfo.sType			= VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
398 	coreInfo.pNext			= &planeInfo;
399 	coreInfo.image			= image;
400 
401 	planeInfo.sType			= VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO;
402 	planeInfo.planeAspect	= planeAspect;
403 
404 	reqs.sType				= VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
405 
406 	vkd.getImageMemoryRequirements2(device, &coreInfo, &reqs);
407 
408 	return reqs.memoryRequirements;
409 }
410 
enumerateInstanceLayerProperties(const PlatformInterface& vkp)411 vector<VkLayerProperties> enumerateInstanceLayerProperties (const PlatformInterface& vkp)
412 {
413 	vector<VkLayerProperties>	properties;
414 	deUint32					numLayers	= 0;
415 
416 	VK_CHECK(vkp.enumerateInstanceLayerProperties(&numLayers, DE_NULL));
417 
418 	if (numLayers > 0)
419 	{
420 		properties.resize(numLayers);
421 		VK_CHECK(vkp.enumerateInstanceLayerProperties(&numLayers, &properties[0]));
422 		TCU_CHECK((size_t)numLayers == properties.size());
423 	}
424 
425 	return properties;
426 }
427 
enumerateInstanceExtensionProperties(const PlatformInterface& vkp, const char* layerName)428 vector<VkExtensionProperties> enumerateInstanceExtensionProperties (const PlatformInterface& vkp, const char* layerName)
429 {
430 	vector<VkExtensionProperties>	properties;
431 	deUint32						numExtensions	= 0;
432 
433 	VK_CHECK(vkp.enumerateInstanceExtensionProperties(layerName, &numExtensions, DE_NULL));
434 
435 	if (numExtensions > 0)
436 	{
437 		properties.resize(numExtensions);
438 		VK_CHECK(vkp.enumerateInstanceExtensionProperties(layerName, &numExtensions, &properties[0]));
439 		TCU_CHECK((size_t)numExtensions == properties.size());
440 	}
441 
442 	return properties;
443 }
444 
enumerateDeviceLayerProperties(const InstanceInterface& vki, VkPhysicalDevice physicalDevice)445 vector<VkLayerProperties> enumerateDeviceLayerProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
446 {
447 	vector<VkLayerProperties>	properties;
448 	deUint32					numLayers	= 0;
449 
450 	VK_CHECK(vki.enumerateDeviceLayerProperties(physicalDevice, &numLayers, DE_NULL));
451 
452 	if (numLayers > 0)
453 	{
454 		properties.resize(numLayers);
455 		VK_CHECK(vki.enumerateDeviceLayerProperties(physicalDevice, &numLayers, &properties[0]));
456 		TCU_CHECK((size_t)numLayers == properties.size());
457 	}
458 
459 	return properties;
460 }
461 
enumerateDeviceExtensionProperties(const InstanceInterface& vki, VkPhysicalDevice physicalDevice, const char* layerName)462 vector<VkExtensionProperties> enumerateDeviceExtensionProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, const char* layerName)
463 {
464 	vector<VkExtensionProperties>	properties;
465 	deUint32						numExtensions	= 0;
466 
467 	VK_CHECK(vki.enumerateDeviceExtensionProperties(physicalDevice, layerName, &numExtensions, DE_NULL));
468 
469 	if (numExtensions > 0)
470 	{
471 		properties.resize(numExtensions);
472 		VK_CHECK(vki.enumerateDeviceExtensionProperties(physicalDevice, layerName, &numExtensions, &properties[0]));
473 		TCU_CHECK((size_t)numExtensions == properties.size());
474 	}
475 
476 	return properties;
477 }
478 
479 namespace
480 {
481 
482 class ExtensionPropertiesCache
483 {
484 protected:
485 	typedef std::pair<const InstanceInterface*, VkPhysicalDevice>	key_type;
486 	typedef std::unique_ptr<std::vector<VkExtensionProperties>>		value_type;
487 
488 public:
ExtensionPropertiesCache()489 	ExtensionPropertiesCache () {}
490 
get(const InstanceInterface& vki, VkPhysicalDevice dev)491 	const std::vector<VkExtensionProperties>* get (const InstanceInterface& vki, VkPhysicalDevice dev)
492 	{
493 		const key_type key(&vki, dev);
494 		const auto itr = m_cache.find(key);
495 		if (itr == m_cache.end())
496 			return nullptr;
497 		return itr->second.get();
498 	}
499 
add(const InstanceInterface& vki, VkPhysicalDevice dev, const std::vector<VkExtensionProperties>& vec)500 	void add (const InstanceInterface& vki, VkPhysicalDevice dev, const std::vector<VkExtensionProperties>& vec)
501 	{
502 		const key_type key(&vki, dev);
503 		m_cache[key].reset(new std::vector<VkExtensionProperties>(vec));
504 	}
505 
506 protected:
507 	std::map<key_type, value_type> m_cache;
508 };
509 
510 } // anonymous namespace
511 
512 // Uses a global cache to avoid copying so many results and obtaining extension lists over and over again.
enumerateCachedDeviceExtensionProperties(const InstanceInterface& vki, VkPhysicalDevice physicalDevice)513 const std::vector<VkExtensionProperties>& enumerateCachedDeviceExtensionProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
514 {
515 	// Find extension properties in the cache.
516 	static ExtensionPropertiesCache m_extensionPropertiesCache;
517 	auto supportedExtensions = m_extensionPropertiesCache.get(vki, physicalDevice);
518 
519 	if (!supportedExtensions)
520 	{
521 		const auto enumeratedExtensions = enumerateDeviceExtensionProperties(vki, physicalDevice, nullptr);
522 		m_extensionPropertiesCache.add(vki, physicalDevice, enumeratedExtensions);
523 		supportedExtensions = m_extensionPropertiesCache.get(vki, physicalDevice);
524 	}
525 
526 	return *supportedExtensions;
527 }
528 
isShaderStageSupported(const VkPhysicalDeviceFeatures& deviceFeatures, VkShaderStageFlagBits stage)529 bool isShaderStageSupported (const VkPhysicalDeviceFeatures& deviceFeatures, VkShaderStageFlagBits stage)
530 {
531 	if (stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
532 		return deviceFeatures.tessellationShader == VK_TRUE;
533 	else if (stage == VK_SHADER_STAGE_GEOMETRY_BIT)
534 		return deviceFeatures.geometryShader == VK_TRUE;
535 	else
536 		return true;
537 }
538 
isCompatible(const VkExtensionProperties& extensionProperties, const RequiredExtension& required)539 bool isCompatible (const VkExtensionProperties& extensionProperties, const RequiredExtension& required)
540 {
541 	if (required.name != extensionProperties.extensionName)
542 		return false;
543 
544 	if (required.minVersion && required.minVersion.get() > extensionProperties.specVersion)
545 		return false;
546 
547 	if (required.maxVersion && required.maxVersion.get() < extensionProperties.specVersion)
548 		return false;
549 
550 	return true;
551 }
552 
isCompatible(const VkLayerProperties& layerProperties, const RequiredLayer& required)553 bool isCompatible (const VkLayerProperties& layerProperties, const RequiredLayer& required)
554 {
555 	if (required.name != layerProperties.layerName)
556 		return false;
557 
558 	if (required.minSpecVersion && required.minSpecVersion.get() > layerProperties.specVersion)
559 		return false;
560 
561 	if (required.maxSpecVersion && required.maxSpecVersion.get() < layerProperties.specVersion)
562 		return false;
563 
564 	if (required.minImplVersion && required.minImplVersion.get() > layerProperties.implementationVersion)
565 		return false;
566 
567 	if (required.maxImplVersion && required.maxImplVersion.get() < layerProperties.implementationVersion)
568 		return false;
569 
570 	return true;
571 }
572 
isExtensionStructSupported(const std::vector<VkExtensionProperties>& extensions, const RequiredExtension& required)573 bool isExtensionStructSupported (const std::vector<VkExtensionProperties>& extensions, const RequiredExtension& required)
574 {
575 	return isExtensionStructSupported(extensions.begin(), extensions.end(), required);
576 }
577 
isExtensionStructSupported(const vector<std::string>& extensionStrings, const std::string& extensionName)578 bool isExtensionStructSupported (const vector<std::string>& extensionStrings, const std::string& extensionName)
579 {
580 	return de::contains(extensionStrings.begin(), extensionStrings.end(), extensionName);
581 }
582 
isInstanceExtensionSupported(const deUint32 instanceVersion, const std::vector<std::string>& extensions, const std::string& required)583 bool isInstanceExtensionSupported(const deUint32 instanceVersion, const std::vector<std::string>& extensions, const std::string& required)
584 {
585 	// NOTE: this function is only needed in few cases during creation of context,
586 	// dont use it, call Context::isInstanceFunctionalitySupported instead
587 	if (isCoreInstanceExtension(instanceVersion, required))
588 		return true;
589 	return de::contains(extensions.begin(), extensions.end(), required);
590 }
591 
isLayerSupported(const std::vector<VkLayerProperties>& layers, const RequiredLayer& required)592 bool isLayerSupported (const std::vector<VkLayerProperties>& layers, const RequiredLayer& required)
593 {
594 	return isLayerSupported(layers.begin(), layers.end(), required);
595 }
596 
getDeviceQueue(const DeviceInterface& vkd, VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex)597 VkQueue getDeviceQueue (const DeviceInterface& vkd, VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex)
598 {
599 	VkQueue queue;
600 
601 	vkd.getDeviceQueue(device, queueFamilyIndex, queueIndex, &queue);
602 
603 	return queue;
604 }
605 
getDeviceQueue2(const DeviceInterface& vkd, VkDevice device, const VkDeviceQueueInfo2* queueInfo)606 VkQueue getDeviceQueue2 (const DeviceInterface& vkd, VkDevice device, const VkDeviceQueueInfo2* queueInfo)
607 {
608 	VkQueue queue;
609 
610 	vkd.getDeviceQueue2(device, queueInfo, &queue);
611 
612 	return queue;
613 }
614 
findStructureInChain(const void* first, VkStructureType type)615 const void* findStructureInChain (const void* first, VkStructureType type)
616 {
617 	struct StructureBase
618 	{
619 		VkStructureType		sType;
620 		void*				pNext;
621 	};
622 
623 	const StructureBase*	cur		= reinterpret_cast<const StructureBase*>(first);
624 
625 	while (cur)
626 	{
627 		if (cur->sType == type)
628 			break;
629 		else
630 			cur = reinterpret_cast<const StructureBase*>(cur->pNext);
631 	}
632 
633 	return cur;
634 }
635 
findStructureInChain(void* first, VkStructureType type)636 void* findStructureInChain (void* first, VkStructureType type)
637 {
638 	return const_cast<void*>(findStructureInChain(const_cast<const void*>(first), type));
639 }
640 
appendStructurePtrToVulkanChain(const void** chainHead, const void* structurePtr)641 void appendStructurePtrToVulkanChain (const void**	chainHead, const void*	structurePtr)
642 {
643 	struct StructureBase
644 	{
645 		VkStructureType		sType;
646 		const void*			pNext;
647 	};
648 
649 	while (*chainHead != DE_NULL)
650 	{
651 		StructureBase* ptr = (StructureBase*)(*chainHead);
652 
653 		chainHead = &(ptr->pNext);
654 	}
655 
656 	(*chainHead) = structurePtr;
657 }
658 
659 // getStructureType<T> implementations
660 #include "vkGetStructureTypeImpl.inl"
661 
662 } // vk
663