1 #ifndef _VKQUERYUTIL_HPP
2 #define _VKQUERYUTIL_HPP
3 /*-------------------------------------------------------------------------
4  * Vulkan CTS Framework
5  * --------------------
6  *
7  * Copyright (c) 2015 Google Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Vulkan query utilities.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vkDefs.hpp"
27 #include "tcuMaybe.hpp"
28 #include "deMemory.h"
29 
30 #include <vector>
31 #include <string>
32 
33 namespace vk
34 {
35 
36 // API version introspection
37 
38 void											getCoreInstanceExtensions						(deUint32 apiVersion, std::vector<const char*>& dst);
39 void											getCoreDeviceExtensions							(deUint32 apiVersion, std::vector<const char*>& dst);
40 bool											isCoreInstanceExtension							(const deUint32 apiVersion, const std::string& extension);
41 bool											isCoreDeviceExtension							(const deUint32 apiVersion, const std::string& extension);
42 
43 // API queries
44 
45 std::vector<VkPhysicalDevice>					enumeratePhysicalDevices						(const InstanceInterface& vk, VkInstance instance);
46 std::vector<VkPhysicalDeviceGroupProperties>	enumeratePhysicalDeviceGroups					(const InstanceInterface& vk, VkInstance instance);
47 std::vector<VkQueueFamilyProperties>			getPhysicalDeviceQueueFamilyProperties			(const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
48 VkPhysicalDeviceFeatures						getPhysicalDeviceFeatures						(const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
49 VkPhysicalDeviceFeatures2						getPhysicalDeviceFeatures2						(const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
50 VkPhysicalDeviceVulkan11Features				getPhysicalDeviceVulkan11Features				(const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
51 VkPhysicalDeviceVulkan12Features				getPhysicalDeviceVulkan12Features				(const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
52 VkPhysicalDeviceVulkan11Properties				getPhysicalDeviceVulkan11Properties				(const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
53 VkPhysicalDeviceVulkan12Properties				getPhysicalDeviceVulkan12Properties				(const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
54 VkPhysicalDeviceProperties						getPhysicalDeviceProperties						(const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
55 VkPhysicalDeviceMemoryProperties				getPhysicalDeviceMemoryProperties				(const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
56 VkFormatProperties								getPhysicalDeviceFormatProperties				(const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format);
57 VkImageFormatProperties							getPhysicalDeviceImageFormatProperties			(const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags);
58 
59 #ifndef CTS_USES_VULKANSC
60 std::vector<VkSparseImageFormatProperties>		getPhysicalDeviceSparseImageFormatProperties	(const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling);
61 #endif // CTS_USES_VULKANSC
62 #ifdef CTS_USES_VULKANSC
63 VkPhysicalDeviceVulkanSC10Features				getPhysicalDeviceVulkanSC10Features				(const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
64 VkPhysicalDeviceVulkanSC10Properties			getPhysicalDeviceVulkanSC10Properties			(const InstanceInterface& vk, VkPhysicalDevice physicalDevice);
65 #endif // CTS_USES_VULKANSC
66 VkMemoryRequirements							getBufferMemoryRequirements						(const DeviceInterface& vk, VkDevice device, VkBuffer buffer);
67 VkMemoryRequirements							getImageMemoryRequirements						(const DeviceInterface& vk, VkDevice device, VkImage image);
68 VkMemoryRequirements							getImagePlaneMemoryRequirements					(const DeviceInterface& vk, VkDevice device, VkImage image, VkImageAspectFlagBits planeAspect);
69 #ifndef CTS_USES_VULKANSC
70 std::vector<VkSparseImageMemoryRequirements>	getImageSparseMemoryRequirements				(const DeviceInterface& vk, VkDevice device, VkImage image);
71 std::vector<vk::VkSparseImageMemoryRequirements>getDeviceImageSparseMemoryRequirements			(const DeviceInterface& vk, VkDevice device, const VkImageCreateInfo& imageCreateInfo, VkImageAspectFlagBits planeAspect);
72 #endif // CTS_USES_VULKANSC
73 
74 std::vector<VkLayerProperties>					enumerateInstanceLayerProperties				(const PlatformInterface& vkp);
75 std::vector<VkExtensionProperties>				enumerateInstanceExtensionProperties			(const PlatformInterface& vkp, const char* layerName);
76 std::vector<VkLayerProperties>					enumerateDeviceLayerProperties					(const InstanceInterface& vki, VkPhysicalDevice physicalDevice);
77 std::vector<VkExtensionProperties>				enumerateDeviceExtensionProperties				(const InstanceInterface& vki, VkPhysicalDevice physicalDevice, const char* layerName);
78 const std::vector<VkExtensionProperties>&		enumerateCachedDeviceExtensionProperties		(const InstanceInterface& vki, VkPhysicalDevice physicalDevice);
79 
80 VkQueue											getDeviceQueue									(const DeviceInterface& vkd, VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex);
81 VkQueue											getDeviceQueue2									(const DeviceInterface& vkd, VkDevice device, const VkDeviceQueueInfo2 *queueInfo);
82 
83 // Feature / extension support
84 
85 bool											isShaderStageSupported							(const VkPhysicalDeviceFeatures& deviceFeatures, VkShaderStageFlagBits stage);
86 
87 struct RequiredExtension
88 {
89 	std::string				name;
90 	tcu::Maybe<deUint32>	minVersion;
91 	tcu::Maybe<deUint32>	maxVersion;
92 
RequiredExtensionvk::RequiredExtension93 	explicit RequiredExtension (const std::string&		name_,
94 								tcu::Maybe<deUint32>	minVersion_ = tcu::Nothing,
95 								tcu::Maybe<deUint32>	maxVersion_ = tcu::Nothing)
96 		: name			(name_)
97 		, minVersion	(minVersion_)
98 		, maxVersion	(maxVersion_)
99 	{}
100 };
101 
102 struct RequiredLayer
103 {
104 	std::string				name;
105 	tcu::Maybe<deUint32>	minSpecVersion;
106 	tcu::Maybe<deUint32>	maxSpecVersion;
107 	tcu::Maybe<deUint32>	minImplVersion;
108 	tcu::Maybe<deUint32>	maxImplVersion;
109 
RequiredLayervk::RequiredLayer110 	explicit RequiredLayer (const std::string&			name_,
111 							tcu::Maybe<deUint32>		minSpecVersion_		= tcu::Nothing,
112 							tcu::Maybe<deUint32>		maxSpecVersion_		= tcu::Nothing,
113 							tcu::Maybe<deUint32>		minImplVersion_		= tcu::Nothing,
114 							tcu::Maybe<deUint32>		maxImplVersion_		= tcu::Nothing)
115 		: name			(name_)
116 		, minSpecVersion(minSpecVersion_)
117 		, maxSpecVersion(maxSpecVersion_)
118 		, minImplVersion(minImplVersion_)
119 		, maxImplVersion(maxImplVersion_)
120 	{}
121 };
122 
123 bool										isCompatible							(const VkExtensionProperties& extensionProperties, const RequiredExtension& required);
124 bool										isCompatible							(const VkLayerProperties& layerProperties, const RequiredLayer& required);
125 
126 template<typename ExtensionIterator>
127 bool										isExtensionStructSupported					(ExtensionIterator begin, ExtensionIterator end, const RequiredExtension& required);
128 bool										isExtensionStructSupported					(const std::vector<VkExtensionProperties>& extensions, const RequiredExtension& required);
129 
130 bool										isInstanceExtensionSupported			(const deUint32 instanceVersion, const std::vector<std::string>& extensions, const std::string& required);
131 
132 template<typename LayerIterator>
133 bool										isLayerSupported						(LayerIterator begin, LayerIterator end, const RequiredLayer& required);
134 bool										isLayerSupported						(const std::vector<VkLayerProperties>& layers, const RequiredLayer& required);
135 
136 const void*									findStructureInChain					(const void* first, VkStructureType type);
137 void*										findStructureInChain					(void* first, VkStructureType type);
138 
139 template<typename StructType>
140 VkStructureType								getStructureType						(void);
141 
142 template<typename StructType>
findStructure(const void* first)143 const StructType*							findStructure							(const void* first)
144 {
145 	return reinterpret_cast<const StructType*>(findStructureInChain(first, getStructureType<StructType>()));
146 }
147 
148 template<typename StructType>
findStructure(void* first)149 StructType*									findStructure							(void* first)
150 {
151 	return reinterpret_cast<StructType*>(findStructureInChain(first, getStructureType<StructType>()));
152 }
153 
154 struct initVulkanStructure
155 {
initVulkanStructurevk::initVulkanStructure156 	initVulkanStructure	(void*	pNext = DE_NULL)	: m_next(pNext)	{}
157 
158 	template<class StructType>
operator StructTypevk::initVulkanStructure159 	operator StructType()
160 	{
161 		StructType result;
162 
163 		deMemset(&result, 0x00, sizeof(StructType));
164 
165 		result.sType	= getStructureType<StructType>();
166 		result.pNext	= m_next;
167 
168 		return result;
169 	}
170 
171 private:
172 	void*	m_next;
173 };
174 
175 template<class StructType>
addToChainVulkanStructure(void*** chainPNextPtr, StructType& structType)176 void addToChainVulkanStructure (void***	chainPNextPtr, StructType&	structType)
177 {
178 	DE_ASSERT(chainPNextPtr != DE_NULL);
179 
180 	(**chainPNextPtr) = &structType;
181 
182 	(*chainPNextPtr) = &structType.pNext;
183 }
184 
185 template<class StructType>
addToChainVulkanStructure(const void*** chainPNextPtr, StructType& structType)186 void addToChainVulkanStructure (const void***	chainPNextPtr, StructType&	structType)
187 {
188 	DE_ASSERT(chainPNextPtr != DE_NULL);
189 
190 	(**chainPNextPtr) = &structType;
191 
192 	(*chainPNextPtr) = &structType.pNext;
193 }
194 
195 struct initVulkanStructureConst
196 {
initVulkanStructureConstvk::initVulkanStructureConst197 	initVulkanStructureConst	(const void*	pNext = DE_NULL)	: m_next(pNext)	{}
198 
199 	template<class StructType>
operator const StructTypevk::initVulkanStructureConst200 	operator const StructType()
201 	{
202 		StructType result;
203 
204 		deMemset(&result, 0x00, sizeof(StructType));
205 
206 		result.sType	= getStructureType<StructType>();
207 		result.pNext	= const_cast<void*>(m_next);
208 
209 		return result;
210 	}
211 
212 private:
213 	const void*	m_next;
214 };
215 
216 struct getPhysicalDeviceExtensionProperties
217 {
getPhysicalDeviceExtensionPropertiesvk::getPhysicalDeviceExtensionProperties218 	getPhysicalDeviceExtensionProperties (const InstanceInterface&	vki, VkPhysicalDevice physicalDevice) : m_vki(vki), m_physicalDevice(physicalDevice) {}
219 
220 	template<class ExtensionProperties>
operator ExtensionPropertiesvk::getPhysicalDeviceExtensionProperties221 	operator ExtensionProperties ()
222 	{
223 		VkPhysicalDeviceProperties2	properties2;
224 		ExtensionProperties			extensionProperties;
225 
226 		deMemset(&extensionProperties, 0x00, sizeof(ExtensionProperties));
227 		extensionProperties.sType = getStructureType<ExtensionProperties>();
228 
229 		deMemset(&properties2, 0x00, sizeof(properties2));
230 		properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
231 		properties2.pNext = &extensionProperties;
232 
233 		m_vki.getPhysicalDeviceProperties2(m_physicalDevice, &properties2);
234 
235 		return extensionProperties;
236 	}
237 
operator VkPhysicalDeviceProperties2vk::getPhysicalDeviceExtensionProperties238 	operator VkPhysicalDeviceProperties2 ()
239 	{
240 		VkPhysicalDeviceProperties2	properties2;
241 
242 		deMemset(&properties2, 0x00, sizeof(properties2));
243 		properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
244 
245 		m_vki.getPhysicalDeviceProperties2(m_physicalDevice, &properties2);
246 
247 		return properties2;
248 	}
249 
250 private:
251 	const InstanceInterface&	m_vki;
252 	const VkPhysicalDevice		m_physicalDevice;
253 };
254 
255 // Walks through chain to find empty pNext and assigns what to found pNext
256 void appendStructurePtrToVulkanChain (const void**	chainHead, const void*	structurePtr);
257 
258 namespace ValidateQueryBits
259 {
260 
261 typedef struct
262 {
263 	size_t		offset;
264 	size_t		size;
265 } QueryMemberTableEntry;
266 
267 template <typename Context, typename Interface, typename Type>
268 //!< Return variable initialization validation
validateInitComplete(Context context, void (Interface::*Function)(Context, Type*)const, const Interface& interface, const QueryMemberTableEntry* queryMemberTableEntry)269 bool validateInitComplete(Context context, void (Interface::*Function)(Context, Type*)const, const Interface& interface, const QueryMemberTableEntry* queryMemberTableEntry)
270 {
271 	const QueryMemberTableEntry	*iterator;
272 	Type vec[2];
273 	deMemset(&vec[0], 0x00, sizeof(Type));
274 	deMemset(&vec[1], 0xFF, sizeof(Type));
275 
276 	(interface.*Function)(context, &vec[0]);
277 	(interface.*Function)(context, &vec[1]);
278 
279 	for (iterator = queryMemberTableEntry; iterator->size != 0; iterator++)
280 	{
281 		if (deMemCmp(((deUint8*)(&vec[0]))+iterator->offset, ((deUint8*)(&vec[1]))+iterator->offset, iterator->size) != 0)
282 			return false;
283 	}
284 
285 	return true;
286 }
287 
288 template <typename Type>
289 //!< Return variable initialization validation
validateStructsWithGuard(const QueryMemberTableEntry* queryMemberTableEntry, Type* vec[2], const deUint8 guardValue, const deUint32 guardSize)290 bool validateStructsWithGuard (const QueryMemberTableEntry* queryMemberTableEntry, Type* vec[2], const deUint8 guardValue, const deUint32 guardSize)
291 {
292 	const QueryMemberTableEntry	*iterator;
293 
294 	for (iterator = queryMemberTableEntry; iterator->size != 0; iterator++)
295 	{
296 		if (deMemCmp(((deUint8*)(vec[0]))+iterator->offset, ((deUint8*)(vec[1]))+iterator->offset, iterator->size) != 0)
297 			return false;
298 	}
299 
300 	for (deUint32 vecNdx = 0; vecNdx < 2; ++vecNdx)
301 	{
302 		for (deUint32 ndx = 0; ndx < guardSize; ndx++)
303 		{
304 			if (((deUint8*)(vec[vecNdx]))[ndx + sizeof(Type)] != guardValue)
305 				return false;
306 		}
307 	}
308 
309 	return true;
310 }
311 
312 template<typename IterT>
313 //! Overwrite a range of objects with an 8-bit pattern.
fillBits(IterT beg, const IterT end, const deUint8 pattern = 0xdeu)314 inline void fillBits (IterT beg, const IterT end, const deUint8 pattern = 0xdeu)
315 {
316 	for (; beg < end; ++beg)
317 		deMemset(&(*beg), static_cast<int>(pattern), sizeof(*beg));
318 }
319 
320 template<typename IterT>
321 //! Verify that each byte of a range of objects is equal to an 8-bit pattern.
checkBits(IterT beg, const IterT end, const deUint8 pattern = 0xdeu)322 bool checkBits (IterT beg, const IterT end, const deUint8 pattern = 0xdeu)
323 {
324 	for (; beg < end; ++beg)
325 	{
326 		const deUint8* elementBytes = reinterpret_cast<const deUint8*>(&(*beg));
327 		for (std::size_t i = 0u; i < sizeof(*beg); ++i)
328 		{
329 			if (elementBytes[i] != pattern)
330 				return false;
331 		}
332 	}
333 	return true;
334 }
335 
336 } // ValidateQueryBits
337 
338 // Template implementations
339 
340 template<typename ExtensionIterator>
isExtensionStructSupported(ExtensionIterator begin, ExtensionIterator end, const RequiredExtension& required)341 bool isExtensionStructSupported (ExtensionIterator begin, ExtensionIterator end, const RequiredExtension& required)
342 {
343 	for (ExtensionIterator cur = begin; cur != end; ++cur)
344 	{
345 		if (isCompatible(*cur, required))
346 			return true;
347 	}
348 	return false;
349 }
350 
351 template<typename LayerIterator>
isLayerSupported(LayerIterator begin, LayerIterator end, const RequiredLayer& required)352 bool isLayerSupported (LayerIterator begin, LayerIterator end, const RequiredLayer& required)
353 {
354 	for (LayerIterator cur = begin; cur != end; ++cur)
355 	{
356 		if (isCompatible(*cur, required))
357 			return true;
358 	}
359 	return false;
360 }
361 
362 } // vk
363 
364 #endif // _VKQUERYUTIL_HPP
365