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