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 std::vector<VkSparseImageFormatProperties> getPhysicalDeviceSparseImageFormatProperties (const InstanceInterface& vk, VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling);
59
60 VkMemoryRequirements getBufferMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkBuffer buffer);
61 VkMemoryRequirements getImageMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkImage image);
62 VkMemoryRequirements getImagePlaneMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkImage image, VkImageAspectFlagBits planeAspect);
63 std::vector<VkSparseImageMemoryRequirements> getImageSparseMemoryRequirements (const DeviceInterface& vk, VkDevice device, VkImage image);
64
65 std::vector<VkLayerProperties> enumerateInstanceLayerProperties (const PlatformInterface& vkp);
66 std::vector<VkExtensionProperties> enumerateInstanceExtensionProperties (const PlatformInterface& vkp, const char* layerName);
67 std::vector<VkLayerProperties> enumerateDeviceLayerProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice);
68 std::vector<VkExtensionProperties> enumerateDeviceExtensionProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, const char* layerName);
69
70 VkQueue getDeviceQueue (const DeviceInterface& vkd, VkDevice device, deUint32 queueFamilyIndex, deUint32 queueIndex);
71 VkQueue getDeviceQueue2 (const DeviceInterface& vkd, VkDevice device, const VkDeviceQueueInfo2 *queueInfo);
72
73 // Feature / extension support
74
75 bool isShaderStageSupported (const VkPhysicalDeviceFeatures& deviceFeatures, VkShaderStageFlagBits stage);
76
77 struct RequiredExtension
78 {
79 std::string name;
80 tcu::Maybe<deUint32> minVersion;
81 tcu::Maybe<deUint32> maxVersion;
82
RequiredExtensionvk::RequiredExtension83 explicit RequiredExtension (const std::string& name_,
84 tcu::Maybe<deUint32> minVersion_ = tcu::nothing<deUint32>(),
85 tcu::Maybe<deUint32> maxVersion_ = tcu::nothing<deUint32>())
86 : name (name_)
87 , minVersion (minVersion_)
88 , maxVersion (maxVersion_)
89 {}
90 };
91
92 struct RequiredLayer
93 {
94 std::string name;
95 tcu::Maybe<deUint32> minSpecVersion;
96 tcu::Maybe<deUint32> maxSpecVersion;
97 tcu::Maybe<deUint32> minImplVersion;
98 tcu::Maybe<deUint32> maxImplVersion;
99
RequiredLayervk::RequiredLayer100 explicit RequiredLayer (const std::string& name_,
101 tcu::Maybe<deUint32> minSpecVersion_ = tcu::nothing<deUint32>(),
102 tcu::Maybe<deUint32> maxSpecVersion_ = tcu::nothing<deUint32>(),
103 tcu::Maybe<deUint32> minImplVersion_ = tcu::nothing<deUint32>(),
104 tcu::Maybe<deUint32> maxImplVersion_ = tcu::nothing<deUint32>())
105 : name (name_)
106 , minSpecVersion(minSpecVersion_)
107 , maxSpecVersion(maxSpecVersion_)
108 , minImplVersion(minImplVersion_)
109 , maxImplVersion(maxImplVersion_)
110 {}
111 };
112
113 bool isCompatible (const VkExtensionProperties& extensionProperties, const RequiredExtension& required);
114 bool isCompatible (const VkLayerProperties& layerProperties, const RequiredLayer& required);
115
116 template<typename ExtensionIterator>
117 bool isExtensionSupported (ExtensionIterator begin, ExtensionIterator end, const RequiredExtension& required);
118 bool isExtensionSupported (const std::vector<VkExtensionProperties>& extensions, const RequiredExtension& required);
119
120 bool isInstanceExtensionSupported (const deUint32 instanceVersion, const std::vector<std::string>& extensions, const std::string& required);
121
122 template<typename LayerIterator>
123 bool isLayerSupported (LayerIterator begin, LayerIterator end, const RequiredLayer& required);
124 bool isLayerSupported (const std::vector<VkLayerProperties>& layers, const RequiredLayer& required);
125
126 const void* findStructureInChain (const void* first, VkStructureType type);
127 void* findStructureInChain (void* first, VkStructureType type);
128
129 template<typename StructType>
130 VkStructureType getStructureType (void);
131
132 template<typename StructType>
findStructure(const void * first)133 const StructType* findStructure (const void* first)
134 {
135 return reinterpret_cast<const StructType*>(findStructureInChain(first, getStructureType<StructType>()));
136 }
137
138 template<typename StructType>
findStructure(void * first)139 StructType* findStructure (void* first)
140 {
141 return reinterpret_cast<StructType*>(findStructureInChain(first, getStructureType<StructType>()));
142 }
143
144 struct initVulkanStructure
145 {
initVulkanStructurevk::initVulkanStructure146 initVulkanStructure (void* pNext = DE_NULL) : m_next(pNext) {};
147
148 template<class StructType>
operator StructTypevk::initVulkanStructure149 operator StructType()
150 {
151 StructType result;
152
153 deMemset(&result, 0x00, sizeof(StructType));
154
155 result.sType = getStructureType<StructType>();
156 result.pNext = m_next;
157
158 return result;
159 }
160
161 private:
162 void* m_next;
163 };
164
165 template<class StructType>
addToChainVulkanStructure(void *** chainPNextPtr,StructType & structType)166 void addToChainVulkanStructure (void*** chainPNextPtr, StructType& structType)
167 {
168 DE_ASSERT(chainPNextPtr != DE_NULL);
169
170 (**chainPNextPtr) = &structType;
171
172 (*chainPNextPtr) = &structType.pNext;
173 }
174
175 struct initVulkanStructureConst
176 {
initVulkanStructureConstvk::initVulkanStructureConst177 initVulkanStructureConst (const void* pNext = DE_NULL) : m_next(pNext) {};
178
179 template<class StructType>
operator const StructTypevk::initVulkanStructureConst180 operator const StructType()
181 {
182 StructType result;
183
184 deMemset(&result, 0x00, sizeof(StructType));
185
186 result.sType = getStructureType<StructType>();
187 result.pNext = const_cast<void*>(m_next);
188
189 return result;
190 }
191
192 private:
193 const void* m_next;
194 };
195
196 struct getPhysicalDeviceExtensionProperties
197 {
getPhysicalDeviceExtensionPropertiesvk::getPhysicalDeviceExtensionProperties198 getPhysicalDeviceExtensionProperties (const InstanceInterface& vki, VkPhysicalDevice physicalDevice) : m_vki(vki), m_physicalDevice(physicalDevice) {};
199
200 template<class ExtensionProperties>
operator ExtensionPropertiesvk::getPhysicalDeviceExtensionProperties201 operator ExtensionProperties ()
202 {
203 VkPhysicalDeviceProperties2 properties2;
204 ExtensionProperties extensionProperties;
205
206 deMemset(&extensionProperties, 0x00, sizeof(ExtensionProperties));
207 extensionProperties.sType = getStructureType<ExtensionProperties>();
208
209 deMemset(&properties2, 0x00, sizeof(properties2));
210 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
211 properties2.pNext = &extensionProperties;
212
213 m_vki.getPhysicalDeviceProperties2(m_physicalDevice, &properties2);
214
215 return extensionProperties;
216 }
217
operator VkPhysicalDeviceProperties2vk::getPhysicalDeviceExtensionProperties218 operator VkPhysicalDeviceProperties2 ()
219 {
220 VkPhysicalDeviceProperties2 properties2;
221
222 deMemset(&properties2, 0x00, sizeof(properties2));
223 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
224
225 m_vki.getPhysicalDeviceProperties2(m_physicalDevice, &properties2);
226
227 return properties2;
228 }
229
230 private:
231 const InstanceInterface& m_vki;
232 const VkPhysicalDevice m_physicalDevice;
233 };
234
235 // Walks through chain to find empty pNext and assigns what to found pNext
236 void appendStructurePtrToVulkanChain (const void** chainHead, const void* structurePtr);
237
238 namespace ValidateQueryBits
239 {
240
241 typedef struct
242 {
243 size_t offset;
244 size_t size;
245 } QueryMemberTableEntry;
246
247 template <typename Context, typename Interface, typename Type>
248 //!< Return variable initialization validation
validateInitComplete(Context context,void (Interface::* Function)(Context,Type *)const,const Interface & interface,const QueryMemberTableEntry * queryMemberTableEntry)249 bool validateInitComplete(Context context, void (Interface::*Function)(Context, Type*)const, const Interface& interface, const QueryMemberTableEntry* queryMemberTableEntry)
250 {
251 const QueryMemberTableEntry *iterator;
252 Type vec[2];
253 deMemset(&vec[0], 0x00, sizeof(Type));
254 deMemset(&vec[1], 0xFF, sizeof(Type));
255
256 (interface.*Function)(context, &vec[0]);
257 (interface.*Function)(context, &vec[1]);
258
259 for (iterator = queryMemberTableEntry; iterator->size != 0; iterator++)
260 {
261 if (deMemCmp(((deUint8*)(&vec[0]))+iterator->offset, ((deUint8*)(&vec[1]))+iterator->offset, iterator->size) != 0)
262 return false;
263 }
264
265 return true;
266 }
267
268 template <typename Type>
269 //!< Return variable initialization validation
validateStructsWithGuard(const QueryMemberTableEntry * queryMemberTableEntry,Type * vec[2],const deUint8 guardValue,const deUint32 guardSize)270 bool validateStructsWithGuard (const QueryMemberTableEntry* queryMemberTableEntry, Type* vec[2], const deUint8 guardValue, const deUint32 guardSize)
271 {
272 const QueryMemberTableEntry *iterator;
273
274 for (iterator = queryMemberTableEntry; iterator->size != 0; iterator++)
275 {
276 if (deMemCmp(((deUint8*)(vec[0]))+iterator->offset, ((deUint8*)(vec[1]))+iterator->offset, iterator->size) != 0)
277 return false;
278 }
279
280 for (deUint32 vecNdx = 0; vecNdx < 2; ++vecNdx)
281 {
282 for (deUint32 ndx = 0; ndx < guardSize; ndx++)
283 {
284 if (((deUint8*)(vec[vecNdx]))[ndx + sizeof(Type)] != guardValue)
285 return false;
286 }
287 }
288
289 return true;
290 }
291
292 template<typename IterT>
293 //! Overwrite a range of objects with an 8-bit pattern.
fillBits(IterT beg,const IterT end,const deUint8 pattern=0xdeu)294 inline void fillBits (IterT beg, const IterT end, const deUint8 pattern = 0xdeu)
295 {
296 for (; beg < end; ++beg)
297 deMemset(&(*beg), static_cast<int>(pattern), sizeof(*beg));
298 }
299
300 template<typename IterT>
301 //! 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)302 bool checkBits (IterT beg, const IterT end, const deUint8 pattern = 0xdeu)
303 {
304 for (; beg < end; ++beg)
305 {
306 const deUint8* elementBytes = reinterpret_cast<const deUint8*>(&(*beg));
307 for (std::size_t i = 0u; i < sizeof(*beg); ++i)
308 {
309 if (elementBytes[i] != pattern)
310 return false;
311 }
312 }
313 return true;
314 }
315
316 } // ValidateQueryBits
317
318 // Template implementations
319
320 template<typename ExtensionIterator>
isExtensionSupported(ExtensionIterator begin,ExtensionIterator end,const RequiredExtension & required)321 bool isExtensionSupported (ExtensionIterator begin, ExtensionIterator end, const RequiredExtension& required)
322 {
323 for (ExtensionIterator cur = begin; cur != end; ++cur)
324 {
325 if (isCompatible(*cur, required))
326 return true;
327 }
328 return false;
329 }
330
331 template<typename LayerIterator>
isLayerSupported(LayerIterator begin,LayerIterator end,const RequiredLayer & required)332 bool isLayerSupported (LayerIterator begin, LayerIterator end, const RequiredLayer& required)
333 {
334 for (LayerIterator cur = begin; cur != end; ++cur)
335 {
336 if (isCompatible(*cur, required))
337 return true;
338 }
339 return false;
340 }
341
342 } // vk
343
344 #endif // _VKQUERYUTIL_HPP
345