Merge vk-gl-cts/vulkan-cts-1.3.2 into vk-gl-cts/main
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / api / vktApiVersionCheck.cpp
1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 *
6 * Copyright (c) 2019 Google Inc.
7 * Copyright (c) 2019 Khronos Group
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 API Version Check test - prints out version info
24 *//*--------------------------------------------------------------------*/
25
26 #include <iostream>
27 #include <typeinfo>
28
29 #include "tcuDefs.hpp"
30 #include "tcuTestCase.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuFunctionLibrary.hpp"
33 #include "tcuPlatform.hpp"
34 #include "tcuCommandLine.hpp"
35
36 #include "vkApiVersion.hpp"
37 #include "vkDefs.hpp"
38 #include "vkPlatform.hpp"
39 #include "vkSafetyCriticalUtil.hpp"
40
41 #include "vktApiVersionCheck.hpp"
42 #include "vktTestCase.hpp"
43 #include "vktCustomInstancesDevices.hpp"
44
45 #include "vkDeviceUtil.hpp"
46 #include "vkQueryUtil.hpp"
47 #include "vkRefUtil.hpp"
48
49 #include "deString.h"
50 #include "deStringUtil.hpp"
51
52 #include <map>
53 #include <vector>
54
55 using namespace vk;
56 using namespace std;
57
58 namespace vkt
59 {
60
61 namespace api
62 {
63
64 namespace
65 {
66
67 #include "vkExtensionFunctions.inl"
68 #include "vkCoreFunctionalities.inl"
69
70 class APIVersionTestInstance : public TestInstance
71 {
72 public:
73                                                                 APIVersionTestInstance  (Context&                               ctx)
74                                                                         : TestInstance  (ctx)
75         {}
76         virtual tcu::TestStatus         iterate                                 (void)
77         {
78                 tcu::TestLog&                   log                                             = m_context.getTestContext().getLog();
79                 const vk::ApiVersion    maxVulkanVersion                = vk::unpackVersion(m_context.getMaximumFrameworkVulkanVersion());
80                 const vk::ApiVersion    instanceVersion                 = vk::unpackVersion(m_context.getAvailableInstanceVersion());
81                 const ::std::string             instanceVersionString   = de::toString(instanceVersion.majorNum) + ::std::string(".") + de::toString(instanceVersion.minorNum) + ::std::string(".") + de::toString(instanceVersion.patchNum);
82                 const vk::ApiVersion    deviceVersion                   = vk::unpackVersion(m_context.getDeviceVersion());
83                 const ::std::string             deviceVersionString             = de::toString(deviceVersion.majorNum) + ::std::string(".") + de::toString(deviceVersion.minorNum) + ::std::string(".") + de::toString(deviceVersion.patchNum);
84                 const vk::ApiVersion    usedApiVersion                  = vk::unpackVersion(m_context.getUsedApiVersion());
85                 const ::std::string             usedApiVersionString    = de::toString(usedApiVersion.majorNum) + ::std::string(".") + de::toString(usedApiVersion.minorNum) + ::std::string(".") + de::toString(usedApiVersion.patchNum);
86
87                 log << tcu::TestLog::Message << "availableInstanceVersion: " << instanceVersion << tcu::TestLog::EndMessage;
88                 log << tcu::TestLog::Message << "deviceVersion: " << deviceVersion << tcu::TestLog::EndMessage;
89                 log << tcu::TestLog::Message << "usedApiVersion: " << usedApiVersion << tcu::TestLog::EndMessage;
90
91                 if (instanceVersion.majorNum > maxVulkanVersion.majorNum || instanceVersion.minorNum > maxVulkanVersion.minorNum)
92                         return tcu::TestStatus::fail(de::toString("This version of CTS does not support a Vulkan instance with version ") + instanceVersionString);
93                 else if (deviceVersion.majorNum > maxVulkanVersion.majorNum || deviceVersion.minorNum > maxVulkanVersion.minorNum)
94                         return tcu::TestStatus::fail(de::toString("This version of CTS does not support Vulkan device version ") + deviceVersionString);
95                 else
96                         return tcu::TestStatus::pass(usedApiVersionString);
97         }
98 };
99
100 class APIVersionTestCase : public TestCase
101 {
102 public:
103                                                         APIVersionTestCase      (tcu::TestContext&              testCtx)
104                                                                 : TestCase      (testCtx, "version", "Prints out API info.")
105         {}
106
107         virtual                                 ~APIVersionTestCase     (void)
108         {}
109         virtual TestInstance*   createInstance          (Context&                               ctx) const
110         {
111                 return new APIVersionTestInstance(ctx);
112         }
113
114 private:
115 };
116
117 class APIEntryPointsTestInstance : public TestInstance
118 {
119 public:
120         struct APIContext
121         {
122                 VkInstance                              instance;
123                 VkDevice                                device;
124                 GetInstanceProcAddrFunc getInstanceProcAddr;
125                 GetDeviceProcAddrFunc   getDeviceProcAddr;
126         };
127
128                                                                 APIEntryPointsTestInstance      (Context&                               ctx)
129                                                                         : TestInstance  (ctx)
130         {
131         }
132
133         virtual tcu::TestStatus         iterate                                         (void)
134         {
135                 tcu::TestLog&                                           log                             = m_context.getTestContext().getLog();
136                 const deUint32                                          apiVersion              = m_context.getUsedApiVersion();
137                 const vk::Platform&                                     platform                = m_context.getTestContext().getPlatform().getVulkanPlatform();
138                 de::MovePtr<vk::Library>                        vkLibrary               = de::MovePtr<vk::Library>(platform.createLibrary(m_context.getTestContext().getCommandLine().getVkLibraryPath()));
139                 const tcu::FunctionLibrary&                     funcLibrary             = vkLibrary->getFunctionLibrary();
140
141                 deUint32                                                        failsQuantity   = 0u;
142
143                 // Tests with default instance and device without extensions
144                 {
145                         CustomInstance                  instance                        = createCustomInstanceFromContext(m_context, DE_NULL, false);
146                         Move<VkDevice>                  device                          = createTestDevice(m_context, instance, vector<string>(), false);
147                         GetInstanceProcAddrFunc getInstanceProcAddr     = reinterpret_cast<GetInstanceProcAddrFunc>(funcLibrary.getFunction("vkGetInstanceProcAddr"));
148                         GetDeviceProcAddrFunc   getDeviceProcAddr       = reinterpret_cast<GetDeviceProcAddrFunc>(getInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
149                         APIContext                              ctx                                     = { instance, *device, getInstanceProcAddr, getDeviceProcAddr };
150
151                         // Check entry points of core functions
152                         {
153                                 ApisMap                                                 functions                       = ApisMap();
154                                 initApisMap(functions);
155                                 ApisMap::const_iterator                 lastGoodVersion         = functions.begin();
156                                 const ApisMap::const_iterator   versionsEnd                     = functions.end();
157                                 for (ApisMap::const_iterator it = lastGoodVersion; it != versionsEnd; ++it)
158                                 {
159                                         if (it->first <= m_context.getUsedApiVersion())
160                                                 lastGoodVersion = it;
161                                 }
162
163                                 log << tcu::TestLog::Message << "Regular check - tries to get core functions from proper vkGet*ProcAddr." << tcu::TestLog::EndMessage;
164                                 const char* const                               regularResult           = regularCheck(ctx, log, failsQuantity, lastGoodVersion->second) ? "Passed" : "Failed";
165                                 log << tcu::TestLog::Message << regularResult << tcu::TestLog::EndMessage;
166
167                                 log << tcu::TestLog::Message << "Cross check - tries to get core functions from improper vkGet*ProcAddr." << tcu::TestLog::EndMessage;
168                                 const char* const                               mixupResult                     = mixupAddressProcCheck(ctx, log, failsQuantity, lastGoodVersion->second) ? "Passed" : "Failed";
169                                 log << tcu::TestLog::Message << mixupResult << tcu::TestLog::EndMessage;
170                         }
171
172                         // Check function entry points of disabled extesions
173                         {
174                                 FunctionInfosList                               extFunctions            = FunctionInfosList();
175                                 extFunctions.push_back(FunctionInfo("vkTrimCommandPoolKHR", FUNCTIONORIGIN_DEVICE));
176                                 extFunctions.push_back(FunctionInfo("vkCmdPushDescriptorSetKHR", FUNCTIONORIGIN_DEVICE));
177                                 extFunctions.push_back(FunctionInfo("vkCreateSamplerYcbcrConversionKHR", FUNCTIONORIGIN_DEVICE));
178                                 extFunctions.push_back(FunctionInfo("vkGetSwapchainStatusKHR", FUNCTIONORIGIN_DEVICE));
179                                 extFunctions.push_back(FunctionInfo("vkCreateSwapchainKHR", FUNCTIONORIGIN_DEVICE));
180                                 extFunctions.push_back(FunctionInfo("vkGetImageSparseMemoryRequirements2KHR", FUNCTIONORIGIN_DEVICE));
181                                 extFunctions.push_back(FunctionInfo("vkBindBufferMemory2KHR", FUNCTIONORIGIN_DEVICE));
182                                 extFunctions.push_back(FunctionInfo("vkImportFenceWin32HandleKHR", FUNCTIONORIGIN_DEVICE));
183                                 extFunctions.push_back(FunctionInfo("vkGetBufferMemoryRequirements2KHR", FUNCTIONORIGIN_DEVICE));
184                                 extFunctions.push_back(FunctionInfo("vkGetImageMemoryRequirements2KHR", FUNCTIONORIGIN_DEVICE));
185
186                                 log << tcu::TestLog::Message << "Disabled extensions check - tries to get functions of disabled extensions from proper vkGet*ProcAddr." << tcu::TestLog::EndMessage;
187                                 const char * const                              result                                  = specialCasesCheck(ctx, log, failsQuantity, extFunctions) ? "Passed" : "Failed";
188                                 log << tcu::TestLog::Message << result << tcu::TestLog::EndMessage;
189                         }
190
191                         // Check special cases
192                         {
193                                 FunctionInfosList                               nonexistingFunctions    = FunctionInfosList();
194                                 for (deUint32 i = 0; i <= FUNCTIONORIGIN_DEVICE; ++i)
195                                 {
196                                         const FunctionOrigin origin = static_cast<FunctionOrigin>(i);
197                                         nonexistingFunctions.push_back(FunctionInfo("vkSomeName", origin));
198                                         nonexistingFunctions.push_back(FunctionInfo("vkNonexistingKHR", origin));
199                                         nonexistingFunctions.push_back(FunctionInfo("", origin));
200                                 }
201
202                                 log << tcu::TestLog::Message << "Special check - tries to get some nonexisting functions from various vkGet*ProcAddr." << tcu::TestLog::EndMessage;
203                                 const char * const                              result                          = specialCasesCheck(ctx, log, failsQuantity, nonexistingFunctions) ? "Passed" : "Failed";
204                                 log << tcu::TestLog::Message << result << tcu::TestLog::EndMessage;
205                         }
206                 }
207
208                 // Tests with instance and device with extensions
209                 {
210                         CustomInstance                  instance                        = createCustomInstanceWithExtensions(m_context, getSupportedInstanceExtensions(apiVersion), DE_NULL, false);
211                         Move<VkDevice>                  device                          = createTestDevice(m_context, instance, getSupportedDeviceExtensions(apiVersion), false);
212                         GetInstanceProcAddrFunc getInstanceProcAddr     = reinterpret_cast<GetInstanceProcAddrFunc>(funcLibrary.getFunction("vkGetInstanceProcAddr"));
213                         GetDeviceProcAddrFunc   getDeviceProcAddr       = reinterpret_cast<GetDeviceProcAddrFunc>(getInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
214                         APIContext                              ctx                                     = { instance, *device, getInstanceProcAddr, getDeviceProcAddr };
215
216                         // Check function entry points of enabled extensions
217                         {
218                                 vector<FunctionInfo>    extFunctions;
219
220                                 // Add supported instance extension functions
221                                 for (size_t instanceExtNdx = 0; instanceExtNdx < DE_LENGTH_OF_ARRAY(instanceExtensionNames); instanceExtNdx++)
222                                 {
223                                         vector<const char*> instanceExtFunctions;
224                                         vector<const char*> deviceExtFunctions;
225
226                                         if (isSupportedInstanceExt(instanceExtensionNames[instanceExtNdx], apiVersion))
227                                         {
228                                                 getInstanceExtensionFunctions(apiVersion, instanceExtensionNames[instanceExtNdx], instanceExtFunctions);
229                                                 getDeviceExtensionFunctions(apiVersion, instanceExtensionNames[instanceExtNdx], deviceExtFunctions);
230                                         }
231
232                                         for (size_t instanceFuncNdx = 0; instanceFuncNdx < instanceExtFunctions.size(); instanceFuncNdx++)
233                                                 extFunctions.push_back(FunctionInfo(instanceExtFunctions[instanceFuncNdx], FUNCTIONORIGIN_INSTANCE));
234
235                                         for (size_t deviceFuncNdx = 0; deviceFuncNdx < deviceExtFunctions.size(); deviceFuncNdx++)
236                                                 extFunctions.push_back(FunctionInfo(deviceExtFunctions[deviceFuncNdx], FUNCTIONORIGIN_DEVICE));
237                                 }
238
239                                 // Add supported device extension functions
240                                 for (size_t deviceExtNdx = 0; deviceExtNdx < DE_LENGTH_OF_ARRAY(deviceExtensionNames); deviceExtNdx++)
241                                 {
242                                         vector<const char*> deviceExtFunctions;
243
244                                         if (isSupportedDeviceExt(deviceExtensionNames[deviceExtNdx], apiVersion))
245                                                 getDeviceExtensionFunctions(apiVersion, deviceExtensionNames[deviceExtNdx], deviceExtFunctions);
246
247                                         for (size_t deviceFuncNdx = 0; deviceFuncNdx < deviceExtFunctions.size(); deviceFuncNdx++)
248                                                 extFunctions.push_back(FunctionInfo(deviceExtFunctions[deviceFuncNdx], FUNCTIONORIGIN_DEVICE));
249                                 }
250
251                                 log << tcu::TestLog::Message << "Enabled extensions check - tries to get functions of supported extensions from proper vkGet*ProcAddr." << tcu::TestLog::EndMessage;
252                                 const char * const              result = regularCheck(ctx, log, failsQuantity, extFunctions) ? "Passed" : "Failed";
253                                 log << tcu::TestLog::Message << result << tcu::TestLog::EndMessage;
254                         }
255                 }
256
257                 if (failsQuantity > 0u)
258                         return tcu::TestStatus::fail("Fail");
259                 else
260                         return tcu::TestStatus::pass("Pass");
261         }
262
263 private:
264
265         deUint32 findQueueFamilyIndex(const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
266         {
267                 deUint32                                                                numQueues = 0;
268                 vkInstance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, DE_NULL);
269                 if (numQueues > 0)
270                 {
271                         vector<VkQueueFamilyProperties>         properties(numQueues);
272                         vkInstance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, &properties[0]);
273                         if (numQueues != static_cast<deUint32>(properties.size()))
274                                 TCU_FAIL("Returned queue family count changes between queries.");
275                         for (deUint32 queueNdx = 0u; queueNdx < numQueues; queueNdx++)
276                                 if ((properties[queueNdx].queueFlags & requiredCaps) == requiredCaps)
277                                         return queueNdx;
278                 }
279                 TCU_FAIL("Returned queue family count was 0.");
280                 return 0u;
281         }
282
283         vector<string> filterMultiAuthorExtensions (vector<VkExtensionProperties> extProperties)
284         {
285                 vector<string>  multiAuthorExtensions;
286                 const char*             extensionGroups[] =
287                 {
288                         "VK_KHR_",
289                         "VK_EXT_"
290                 };
291
292                 for (size_t extNdx = 0; extNdx < extProperties.size(); extNdx++)
293                 {
294                         for (int extGroupNdx = 0; extGroupNdx < DE_LENGTH_OF_ARRAY(extensionGroups); extGroupNdx++)
295                         {
296                                 if (deStringBeginsWith(extProperties[extNdx].extensionName, extensionGroups[extGroupNdx]))
297                                         multiAuthorExtensions.push_back(extProperties[extNdx].extensionName);
298                         }
299                 }
300
301                 return multiAuthorExtensions;
302         }
303
304         vector<string> getSupportedInstanceExtensions (const deUint32 apiVersion)
305         {
306                 vector<VkExtensionProperties>   enumeratedExtensions (enumerateInstanceExtensionProperties(m_context.getPlatformInterface(), DE_NULL));
307                 vector<VkExtensionProperties>   supportedExtensions;
308
309                 for (size_t extNdx = 0; extNdx < enumeratedExtensions.size(); extNdx++)
310                 {
311                         if (!isCoreInstanceExtension(apiVersion, enumeratedExtensions[extNdx].extensionName))
312                                 supportedExtensions.push_back(enumeratedExtensions[extNdx]);
313                 }
314
315                 return filterMultiAuthorExtensions(supportedExtensions);
316         }
317
318         vector<string> getSupportedDeviceExtensions (const deUint32 apiVersion)
319         {
320                 vector<VkExtensionProperties>   enumeratedExtensions (enumerateDeviceExtensionProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), DE_NULL));
321                 vector<VkExtensionProperties>   supportedExtensions;
322
323                 for (size_t extNdx = 0; extNdx < enumeratedExtensions.size(); extNdx++)
324                 {
325                         if (!isCoreDeviceExtension(apiVersion, enumeratedExtensions[extNdx].extensionName))
326                                 supportedExtensions.push_back(enumeratedExtensions[extNdx]);
327                 }
328
329                 return filterMultiAuthorExtensions(supportedExtensions);
330         }
331
332         Move<VkDevice> createTestDevice (const Context& context, VkInstance instance, vector<string> extensions = vector<string>(), bool allowLayers = true)
333         {
334                 auto&                                           cmdLine                 = context.getTestContext().getCommandLine();
335                 const PlatformInterface&        vkp                             = context.getPlatformInterface();
336                 const InstanceInterface&        vki                             = context.getInstanceInterface();
337                 VkPhysicalDevice                        physicalDevice  = chooseDevice(context.getInstanceInterface(), instance, cmdLine);
338                 vector<const char*>                     extensionPtrs;
339                 const float                                     queuePriority   = 1.0f;
340                 const deUint32                          queueIndex              = findQueueFamilyIndex(vki, physicalDevice, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
341
342                 for (size_t i = 0; i < extensions.size(); i++)
343                         extensionPtrs.push_back(extensions[i].c_str());
344
345                 VkDeviceQueueCreateInfo         queueInfo               = {
346                         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
347                         DE_NULL,
348                         static_cast<VkDeviceQueueCreateFlags>(0u),
349                         queueIndex,
350                         1u,
351                         &queuePriority
352                 };
353
354                 void* pNext                                                                     = DE_NULL;
355 #ifdef CTS_USES_VULKANSC
356                 VkDeviceObjectReservationCreateInfo memReservationInfo  = context.getTestContext().getCommandLine().isSubProcess() ? context.getResourceInterface()->getStatMax() : resetDeviceObjectReservationCreateInfo();
357                 memReservationInfo.pNext                                                                = pNext;
358                 pNext                                                                                                   = &memReservationInfo;
359
360                 VkPhysicalDeviceVulkanSC10Features sc10Features                 = createDefaultSC10Features();
361                 sc10Features.pNext                                                                              = pNext;
362                 pNext                                                                                                   = &sc10Features;
363
364                 VkPipelineCacheCreateInfo                       pcCI;
365                 std::vector<VkPipelinePoolSize>         poolSizes;
366                 if (context.getTestContext().getCommandLine().isSubProcess())
367                 {
368                         if (context.getResourceInterface()->getCacheDataSize() > 0)
369                         {
370                                 pcCI =
371                                 {
372                                         VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,           // VkStructureType                              sType;
373                                         DE_NULL,                                                                                        // const void*                                  pNext;
374                                         VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
375                                                 VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT,   // VkPipelineCacheCreateFlags   flags;
376                                         context.getResourceInterface()->getCacheDataSize(),     // deUintptr                                    initialDataSize;
377                                         context.getResourceInterface()->getCacheData()          // const void*                                  pInitialData;
378                                 };
379                                 memReservationInfo.pipelineCacheCreateInfoCount         = 1;
380                                 memReservationInfo.pPipelineCacheCreateInfos            = &pcCI;
381                         }
382
383                         poolSizes                                                       = context.getResourceInterface()->getPipelinePoolSizes();
384                         if (!poolSizes.empty())
385                         {
386                                 memReservationInfo.pipelinePoolSizeCount                = deUint32(poolSizes.size());
387                                 memReservationInfo.pPipelinePoolSizes                   = poolSizes.data();
388                         }
389                 }
390 #endif // CTS_USES_VULKANSC
391
392                 const VkDeviceCreateInfo        deviceInfo              = {
393                         VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
394                         pNext,
395                         static_cast<VkDeviceCreateFlags>(0u),
396                         1u,
397                         &queueInfo,
398                         0u,
399                         DE_NULL,
400                         (deUint32)extensions.size(),
401                         extensions.size() ? &extensionPtrs[0] : DE_NULL,
402                         DE_NULL,
403                 };
404
405                 const bool                                      validationEnabled = (cmdLine.isValidationEnabled() && allowLayers);
406                 return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceInfo);
407         }
408
409         void reportFail (tcu::TestLog& log, const char* const functionName, const char* const firstParamName, const char* const secondParamName, deBool shouldBeNonNull, deUint32& failsQuantity)
410         {
411                 log << tcu::TestLog::Message
412                         << "[" << failsQuantity << "] " << functionName << '(' << firstParamName << ", \"" << secondParamName << "\") "
413                         << "returned " << (shouldBeNonNull ? "nullptr" : "non-null") << ". Should return " << (shouldBeNonNull ? "valid function address." : "nullptr.")
414                         << tcu::TestLog::EndMessage;
415                 ++failsQuantity;
416         }
417
418         void checkPlatformFunction (const APIContext& ctx, tcu::TestLog& log, const char* const name, deBool shouldBeNonNull, deUint32& failsQuantity)
419         {
420                 if ((ctx.getInstanceProcAddr(DE_NULL, name) == DE_NULL) == shouldBeNonNull)
421                         reportFail(log, "vkGetInstanceProcAddr", "DE_NULL", name, shouldBeNonNull, failsQuantity);
422         }
423
424         void checkInstanceFunction (const APIContext& ctx, tcu::TestLog& log, const char* const name, deBool shouldBeNonNull, deUint32& failsQuantity)
425         {
426                 if ((ctx.getInstanceProcAddr(ctx.instance, name) == DE_NULL) == shouldBeNonNull)
427                         reportFail(log, "vkGetInstanceProcAddr", "instance", name, shouldBeNonNull, failsQuantity);
428         }
429
430         void checkDeviceFunction (const APIContext& ctx, tcu::TestLog& log, const char* const name, deBool shouldBeNonNull, deUint32& failsQuantity)
431         {
432                 if ((ctx.getDeviceProcAddr(ctx.device, name) == DE_NULL) == shouldBeNonNull)
433                         reportFail(log, "vkGetDeviceProcAddr", "device", name, shouldBeNonNull, failsQuantity);
434         }
435
436         deBool isSupportedInstanceExt (const string extName, const deUint32 apiVersion)
437         {
438                 const vector<string> supportedInstanceExtensions (getSupportedInstanceExtensions(apiVersion));
439
440                 return de::contains(supportedInstanceExtensions.begin(), supportedInstanceExtensions.end(), extName);
441         }
442
443         deBool isSupportedDeviceExt (const string extName, const deUint32 apiVersion)
444         {
445                 const vector<string> supportedDeviceExtensions (getSupportedDeviceExtensions(apiVersion));
446
447                 return de::contains(supportedDeviceExtensions.begin(), supportedDeviceExtensions.end(), extName);
448         }
449
450         deBool mixupAddressProcCheck (const APIContext& ctx, tcu::TestLog& log, deUint32& failsQuantity, const vector<pair<const char*, FunctionOrigin> >& testsArr)
451         {
452                 const deUint32 startingQuantity = failsQuantity;
453                 for (deUint32 ndx = 0u; ndx < testsArr.size(); ++ndx)
454                 {
455                         if (deStringEqual(testsArr[ndx].first, "vkGetInstanceProcAddr") || deStringEqual(testsArr[ndx].first, "vkEnumerateInstanceVersion"))
456                                 continue;
457
458                         const char*        functionName = testsArr[ndx].first;
459                         const deUint32 functionType = testsArr[ndx].second;
460                         if (functionType == FUNCTIONORIGIN_INSTANCE)
461                         {
462                                 checkPlatformFunction(ctx, log, functionName, DE_FALSE, failsQuantity);
463                                 checkDeviceFunction(ctx, log, functionName, DE_FALSE, failsQuantity);
464                         }
465                         else if (functionType == FUNCTIONORIGIN_DEVICE)
466                                 checkPlatformFunction(ctx, log, functionName, DE_FALSE, failsQuantity);
467                 }
468                 return startingQuantity == failsQuantity;
469         }
470
471         deBool specialCasesCheck (const APIContext& ctx, tcu::TestLog& log, deUint32& failsQuantity, const vector<pair<const char*, FunctionOrigin> >& testsArr)
472         {
473                 const deUint32 startingQuantity = failsQuantity;
474                 for (deUint32 ndx = 0u; ndx < testsArr.size(); ++ndx)
475                 {
476                         const deUint32 functionType = testsArr[ndx].second;
477                         if (functionType == FUNCTIONORIGIN_PLATFORM)
478                                 checkPlatformFunction(ctx, log, testsArr[ndx].first, DE_FALSE, failsQuantity);
479                         else if (functionType == FUNCTIONORIGIN_INSTANCE)
480                                 checkInstanceFunction(ctx, log, testsArr[ndx].first, DE_FALSE, failsQuantity);
481                         else if (functionType == FUNCTIONORIGIN_DEVICE)
482                                 checkDeviceFunction(ctx, log, testsArr[ndx].first, DE_FALSE, failsQuantity);
483                 }
484                 return startingQuantity == failsQuantity;
485         }
486
487         deBool regularCheck (const APIContext& ctx, tcu::TestLog& log, deUint32& failsQuantity, const vector<pair<const char*, FunctionOrigin> >& testsArr)
488         {
489                 const deUint32 startingQuantity = failsQuantity;
490
491                 for (deUint32 ndx = 0u; ndx < testsArr.size(); ++ndx)
492                 {
493                         const auto&     funcName        = testsArr[ndx].first;
494                         const auto&     funcType        = testsArr[ndx].second;
495                         const auto      apiVersion      = m_context.getUsedApiVersion();
496
497                         if (deStringEqual(funcName, "vkGetInstanceProcAddr") && apiVersion < VK_API_VERSION_1_2)
498                                 continue;
499
500                         // VK_KHR_draw_indirect_count was promoted to core in Vulkan 1.2, but these entrypoints are not mandatory unless the
501                         // device supports the extension. In that case, the drawIndirectCount feature bit will also be true. Any of the two
502                         // checks is valid. We use the extension name for convenience here.
503                         if ((deStringEqual(funcName, "vkCmdDrawIndirectCount") || deStringEqual(funcName, "vkCmdDrawIndexedIndirectCount"))
504                                 && !isSupportedDeviceExt("VK_KHR_draw_indirect_count", apiVersion))
505                                 continue;
506
507                         if (funcType == FUNCTIONORIGIN_PLATFORM)
508                         {
509                                 checkPlatformFunction(ctx, log, funcName, DE_TRUE, failsQuantity);
510                         }
511                         else if (funcType == FUNCTIONORIGIN_INSTANCE)
512                         {
513                                 checkInstanceFunction(ctx, log, funcName, DE_TRUE, failsQuantity);
514                                 checkDeviceFunction(ctx, log, funcName, DE_FALSE, failsQuantity);
515                         }
516                         else if (funcType == FUNCTIONORIGIN_DEVICE)
517                         {
518                                 checkInstanceFunction(ctx, log, funcName, DE_TRUE, failsQuantity);
519                                 checkDeviceFunction(ctx, log, funcName, DE_TRUE, failsQuantity);
520                         }
521                 }
522
523                 return startingQuantity == failsQuantity;
524         }
525 };
526
527 class APIEntryPointsTestCase : public TestCase
528 {
529 public:
530                                                         APIEntryPointsTestCase                  (tcu::TestContext&              testCtx)
531                                                                 : TestCase      (testCtx, "entry_points", "Prints out API info.")
532         {}
533
534         virtual                                 ~APIEntryPointsTestCase                 (void)
535         {}
536         virtual TestInstance*   createInstance                                  (Context&                               ctx) const
537         {
538                 return new APIEntryPointsTestInstance(ctx);
539         }
540
541 private:
542 };
543
544 } // anonymous
545
546 tcu::TestCaseGroup*                     createVersionSanityCheckTests   (tcu::TestContext & testCtx)
547 {
548         de::MovePtr<tcu::TestCaseGroup> versionTests    (new tcu::TestCaseGroup(testCtx, "version_check", "API Version Tests"));
549         versionTests->addChild(new APIVersionTestCase(testCtx));
550         versionTests->addChild(new APIEntryPointsTestCase(testCtx));
551         return versionTests.release();
552 }
553
554 } // api
555
556 } // vkt