1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
6 * Copyright (c) 2019 Google Inc.
7 * Copyright (c) 2019 Khronos Group
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 * \brief API Version Check test - prints out version info
24 *//*--------------------------------------------------------------------*/
29 #include "tcuDefs.hpp"
30 #include "tcuTestCase.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuFunctionLibrary.hpp"
33 #include "tcuPlatform.hpp"
34 #include "tcuCommandLine.hpp"
36 #include "vkApiVersion.hpp"
38 #include "vkPlatform.hpp"
40 #include "vktApiVersionCheck.hpp"
41 #include "vktTestCase.hpp"
42 #include "vktCustomInstancesDevices.hpp"
44 #include "vkDeviceUtil.hpp"
45 #include "vkQueryUtil.hpp"
46 #include "vkRefUtil.hpp"
49 #include "deStringUtil.hpp"
66 #include "vkExtensionFunctions.inl"
67 #include "vkCoreFunctionalities.inl"
69 class APIVersionTestInstance : public TestInstance
72 APIVersionTestInstance (Context& ctx)
75 virtual tcu::TestStatus iterate (void)
77 tcu::TestLog& log = m_context.getTestContext().getLog();
78 const vk::ApiVersion maxVulkanVersion = vk::unpackVersion(m_context.getMaximumFrameworkVulkanVersion());
79 const vk::ApiVersion instanceVersion = vk::unpackVersion(m_context.getAvailableInstanceVersion());
80 const ::std::string instanceVersionString = de::toString(instanceVersion.majorNum) + ::std::string(".") + de::toString(instanceVersion.minorNum) + ::std::string(".") + de::toString(instanceVersion.patchNum);
81 const vk::ApiVersion deviceVersion = vk::unpackVersion(m_context.getDeviceVersion());
82 const ::std::string deviceVersionString = de::toString(deviceVersion.majorNum) + ::std::string(".") + de::toString(deviceVersion.minorNum) + ::std::string(".") + de::toString(deviceVersion.patchNum);
83 const vk::ApiVersion usedApiVersion = vk::unpackVersion(m_context.getUsedApiVersion());
84 const ::std::string usedApiVersionString = de::toString(usedApiVersion.majorNum) + ::std::string(".") + de::toString(usedApiVersion.minorNum) + ::std::string(".") + de::toString(usedApiVersion.patchNum);
86 log << tcu::TestLog::Message << "availableInstanceVersion: " << instanceVersion << tcu::TestLog::EndMessage;
87 log << tcu::TestLog::Message << "deviceVersion: " << deviceVersion << tcu::TestLog::EndMessage;
88 log << tcu::TestLog::Message << "usedApiVersion: " << usedApiVersion << tcu::TestLog::EndMessage;
90 if (instanceVersion.majorNum > maxVulkanVersion.majorNum || instanceVersion.minorNum > maxVulkanVersion.minorNum)
91 return tcu::TestStatus::fail(de::toString("This version of CTS does not support a Vulkan instance with version ") + instanceVersionString);
92 else if (deviceVersion.majorNum > maxVulkanVersion.majorNum || deviceVersion.minorNum > maxVulkanVersion.minorNum)
93 return tcu::TestStatus::fail(de::toString("This version of CTS does not support Vulkan device version ") + deviceVersionString);
95 return tcu::TestStatus::pass(usedApiVersionString);
99 class APIVersionTestCase : public TestCase
102 APIVersionTestCase (tcu::TestContext& testCtx)
103 : TestCase (testCtx, "version", "Prints out API info.")
106 virtual ~APIVersionTestCase (void)
108 virtual TestInstance* createInstance (Context& ctx) const
110 return new APIVersionTestInstance(ctx);
116 class APIEntryPointsTestInstance : public TestInstance
123 GetInstanceProcAddrFunc getInstanceProcAddr;
124 GetDeviceProcAddrFunc getDeviceProcAddr;
127 APIEntryPointsTestInstance (Context& ctx)
132 virtual tcu::TestStatus iterate (void)
134 tcu::TestLog& log = m_context.getTestContext().getLog();
135 const deUint32 apiVersion = m_context.getUsedApiVersion();
136 const vk::Platform& platform = m_context.getTestContext().getPlatform().getVulkanPlatform();
137 de::MovePtr<vk::Library> vkLibrary = de::MovePtr<vk::Library>(platform.createLibrary());
138 const tcu::FunctionLibrary& funcLibrary = vkLibrary->getFunctionLibrary();
140 deUint32 failsQuantity = 0u;
142 // Tests with default instance and device without extensions
144 CustomInstance instance = createCustomInstanceFromContext(m_context, DE_NULL, false);
145 Move<VkDevice> device = createTestDevice(m_context, instance, vector<string>(), false);
146 GetInstanceProcAddrFunc getInstanceProcAddr = reinterpret_cast<GetInstanceProcAddrFunc>(funcLibrary.getFunction("vkGetInstanceProcAddr"));
147 GetDeviceProcAddrFunc getDeviceProcAddr = reinterpret_cast<GetDeviceProcAddrFunc>(getInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
148 APIContext ctx = { instance, *device, getInstanceProcAddr, getDeviceProcAddr };
150 // Check entry points of core functions
152 ApisMap functions = ApisMap();
153 initApisMap(functions);
154 ApisMap::const_iterator lastGoodVersion = functions.begin();
155 const ApisMap::const_iterator versionsEnd = functions.end();
156 for (ApisMap::const_iterator it = lastGoodVersion; it != versionsEnd; ++it)
158 if (it->first <= m_context.getUsedApiVersion())
159 lastGoodVersion = it;
162 log << tcu::TestLog::Message << "Regular check - tries to get core functions from proper vkGet*ProcAddr." << tcu::TestLog::EndMessage;
163 const char* const regularResult = regularCheck(ctx, log, failsQuantity, lastGoodVersion->second) ? "Passed" : "Failed";
164 log << tcu::TestLog::Message << regularResult << tcu::TestLog::EndMessage;
166 log << tcu::TestLog::Message << "Cross check - tries to get core functions from improper vkGet*ProcAddr." << tcu::TestLog::EndMessage;
167 const char* const mixupResult = mixupAddressProcCheck(ctx, log, failsQuantity, lastGoodVersion->second) ? "Passed" : "Failed";
168 log << tcu::TestLog::Message << mixupResult << tcu::TestLog::EndMessage;
171 // Check function entry points of disabled extesions
173 FunctionInfosList extFunctions = FunctionInfosList();
174 extFunctions.push_back(FunctionInfo("vkTrimCommandPoolKHR", FUNCTIONORIGIN_DEVICE));
175 extFunctions.push_back(FunctionInfo("vkCmdPushDescriptorSetKHR", FUNCTIONORIGIN_DEVICE));
176 extFunctions.push_back(FunctionInfo("vkCreateSamplerYcbcrConversionKHR", FUNCTIONORIGIN_DEVICE));
177 extFunctions.push_back(FunctionInfo("vkGetSwapchainStatusKHR", FUNCTIONORIGIN_DEVICE));
178 extFunctions.push_back(FunctionInfo("vkCreateSwapchainKHR", FUNCTIONORIGIN_DEVICE));
179 extFunctions.push_back(FunctionInfo("vkGetImageSparseMemoryRequirements2KHR", FUNCTIONORIGIN_DEVICE));
180 extFunctions.push_back(FunctionInfo("vkBindBufferMemory2KHR", FUNCTIONORIGIN_DEVICE));
181 extFunctions.push_back(FunctionInfo("vkImportFenceWin32HandleKHR", FUNCTIONORIGIN_DEVICE));
182 extFunctions.push_back(FunctionInfo("vkGetBufferMemoryRequirements2KHR", FUNCTIONORIGIN_DEVICE));
183 extFunctions.push_back(FunctionInfo("vkGetImageMemoryRequirements2KHR", FUNCTIONORIGIN_DEVICE));
185 log << tcu::TestLog::Message << "Disabled extensions check - tries to get functions of disabled extensions from proper vkGet*ProcAddr." << tcu::TestLog::EndMessage;
186 const char * const result = specialCasesCheck(ctx, log, failsQuantity, extFunctions) ? "Passed" : "Failed";
187 log << tcu::TestLog::Message << result << tcu::TestLog::EndMessage;
190 // Check special cases
192 FunctionInfosList dummyFunctions = FunctionInfosList();
193 for (deUint32 i = 0; i <= FUNCTIONORIGIN_DEVICE; ++i)
195 const FunctionOrigin origin = static_cast<FunctionOrigin>(i);
196 dummyFunctions.push_back(FunctionInfo("vkSomeName", origin));
197 dummyFunctions.push_back(FunctionInfo("vkNonexistingKHR", origin));
198 dummyFunctions.push_back(FunctionInfo("", origin));
201 log << tcu::TestLog::Message << "Special check - tries to get some dummy functions from various vkGet*ProcAddr." << tcu::TestLog::EndMessage;
202 const char * const result = specialCasesCheck(ctx, log, failsQuantity, dummyFunctions) ? "Passed" : "Failed";
203 log << tcu::TestLog::Message << result << tcu::TestLog::EndMessage;
207 // Tests with instance and device with extensions
209 CustomInstance instance = createCustomInstanceWithExtensions(m_context, getSupportedInstanceExtensions(apiVersion), DE_NULL, false);
210 Move<VkDevice> device = createTestDevice(m_context, instance, getSupportedDeviceExtensions(apiVersion), false);
211 GetInstanceProcAddrFunc getInstanceProcAddr = reinterpret_cast<GetInstanceProcAddrFunc>(funcLibrary.getFunction("vkGetInstanceProcAddr"));
212 GetDeviceProcAddrFunc getDeviceProcAddr = reinterpret_cast<GetDeviceProcAddrFunc>(getInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
213 APIContext ctx = { instance, *device, getInstanceProcAddr, getDeviceProcAddr };
215 // Check function entry points of enabled extensions
217 vector<FunctionInfo> extFunctions;
219 // Add supported instance extension functions
220 for (size_t instanceExtNdx = 0; instanceExtNdx < DE_LENGTH_OF_ARRAY(instanceExtensionNames); instanceExtNdx++)
222 vector<const char*> instanceExtFunctions;
223 vector<const char*> deviceExtFunctions;
225 if (isSupportedInstanceExt(instanceExtensionNames[instanceExtNdx], apiVersion))
227 getInstanceExtensionFunctions(apiVersion, instanceExtensionNames[instanceExtNdx], instanceExtFunctions);
228 getDeviceExtensionFunctions(apiVersion, instanceExtensionNames[instanceExtNdx], deviceExtFunctions);
231 for (size_t instanceFuncNdx = 0; instanceFuncNdx < instanceExtFunctions.size(); instanceFuncNdx++)
232 extFunctions.push_back(FunctionInfo(instanceExtFunctions[instanceFuncNdx], FUNCTIONORIGIN_INSTANCE));
234 for (size_t deviceFuncNdx = 0; deviceFuncNdx < deviceExtFunctions.size(); deviceFuncNdx++)
235 extFunctions.push_back(FunctionInfo(deviceExtFunctions[deviceFuncNdx], FUNCTIONORIGIN_DEVICE));
238 // Add supported device extension functions
239 for (size_t deviceExtNdx = 0; deviceExtNdx < DE_LENGTH_OF_ARRAY(deviceExtensionNames); deviceExtNdx++)
241 vector<const char*> deviceExtFunctions;
243 if (isSupportedDeviceExt(deviceExtensionNames[deviceExtNdx], apiVersion))
244 getDeviceExtensionFunctions(apiVersion, deviceExtensionNames[deviceExtNdx], deviceExtFunctions);
246 for (size_t deviceFuncNdx = 0; deviceFuncNdx < deviceExtFunctions.size(); deviceFuncNdx++)
247 extFunctions.push_back(FunctionInfo(deviceExtFunctions[deviceFuncNdx], FUNCTIONORIGIN_DEVICE));
250 log << tcu::TestLog::Message << "Enabled extensions check - tries to get functions of supported extensions from proper vkGet*ProcAddr." << tcu::TestLog::EndMessage;
251 const char * const result = regularCheck(ctx, log, failsQuantity, extFunctions) ? "Passed" : "Failed";
252 log << tcu::TestLog::Message << result << tcu::TestLog::EndMessage;
256 if (failsQuantity > 0u)
257 return tcu::TestStatus::fail("Fail");
259 return tcu::TestStatus::pass("Pass");
264 deUint32 findQueueFamilyIndex(const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
266 deUint32 numQueues = 0;
267 vkInstance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, DE_NULL);
270 vector<VkQueueFamilyProperties> properties(numQueues);
271 vkInstance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, &properties[0]);
272 if (numQueues != static_cast<deUint32>(properties.size()))
273 TCU_FAIL("Returned queue family count changes between queries.");
274 for (deUint32 queueNdx = 0u; queueNdx < numQueues; queueNdx++)
275 if ((properties[queueNdx].queueFlags & requiredCaps) == requiredCaps)
278 TCU_FAIL("Returned queue family count was 0.");
282 vector<string> filterMultiAuthorExtensions (vector<VkExtensionProperties> extProperties)
284 vector<string> multiAuthorExtensions;
285 const char* extensionGroups[] =
291 for (size_t extNdx = 0; extNdx < extProperties.size(); extNdx++)
293 for (int extGroupNdx = 0; extGroupNdx < DE_LENGTH_OF_ARRAY(extensionGroups); extGroupNdx++)
295 if (deStringBeginsWith(extProperties[extNdx].extensionName, extensionGroups[extGroupNdx]))
296 multiAuthorExtensions.push_back(extProperties[extNdx].extensionName);
300 return multiAuthorExtensions;
303 vector<string> getSupportedInstanceExtensions (const deUint32 apiVersion)
305 vector<VkExtensionProperties> enumeratedExtensions (enumerateInstanceExtensionProperties(m_context.getPlatformInterface(), DE_NULL));
306 vector<VkExtensionProperties> supportedExtensions;
308 for (size_t extNdx = 0; extNdx < enumeratedExtensions.size(); extNdx++)
310 if (!isCoreInstanceExtension(apiVersion, enumeratedExtensions[extNdx].extensionName))
311 supportedExtensions.push_back(enumeratedExtensions[extNdx]);
314 return filterMultiAuthorExtensions(supportedExtensions);
317 vector<string> getSupportedDeviceExtensions (const deUint32 apiVersion)
319 vector<VkExtensionProperties> enumeratedExtensions (enumerateDeviceExtensionProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), DE_NULL));
320 vector<VkExtensionProperties> supportedExtensions;
322 for (size_t extNdx = 0; extNdx < enumeratedExtensions.size(); extNdx++)
324 if (!isCoreDeviceExtension(apiVersion, enumeratedExtensions[extNdx].extensionName))
325 supportedExtensions.push_back(enumeratedExtensions[extNdx]);
328 return filterMultiAuthorExtensions(supportedExtensions);
331 Move<VkDevice> createTestDevice (const Context& context, VkInstance instance, vector<string> extensions = vector<string>(), bool allowLayers = true)
333 auto& cmdLine = context.getTestContext().getCommandLine();
334 const PlatformInterface& vkp = context.getPlatformInterface();
335 const InstanceInterface& vki = context.getInstanceInterface();
336 VkPhysicalDevice physicalDevice = chooseDevice(context.getInstanceInterface(), instance, cmdLine);
337 vector<const char*> extensionPtrs;
338 const float queuePriority = 1.0f;
339 const deUint32 queueIndex = findQueueFamilyIndex(vki, physicalDevice, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
341 for (size_t i = 0; i < extensions.size(); i++)
342 extensionPtrs.push_back(extensions[i].c_str());
344 VkDeviceQueueCreateInfo queueInfo = {
345 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
347 static_cast<VkDeviceQueueCreateFlags>(0u),
353 const VkDeviceCreateInfo deviceInfo = {
354 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
356 static_cast<VkDeviceCreateFlags>(0u),
361 (deUint32)extensions.size(),
362 extensions.size() ? &extensionPtrs[0] : DE_NULL,
366 const bool validationEnabled = (cmdLine.isValidationEnabled() && allowLayers);
367 return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceInfo);
370 void reportFail (tcu::TestLog& log, const char* const functionName, const char* const firstParamName, const char* const secondParamName, deBool shouldBeNonNull, deUint32& failsQuantity)
372 log << tcu::TestLog::Message
373 << "[" << failsQuantity << "] " << functionName << '(' << firstParamName << ", \"" << secondParamName << "\") "
374 << "returned " << (shouldBeNonNull ? "nullptr" : "non-null") << ". Should return " << (shouldBeNonNull ? "valid function address." : "nullptr.")
375 << tcu::TestLog::EndMessage;
379 void checkPlatformFunction (const APIContext& ctx, tcu::TestLog& log, const char* const name, deBool shouldBeNonNull, deUint32& failsQuantity)
381 if ((ctx.getInstanceProcAddr(DE_NULL, name) == DE_NULL) == shouldBeNonNull)
382 reportFail(log, "vkGetInstanceProcAddr", "DE_NULL", name, shouldBeNonNull, failsQuantity);
385 void checkInstanceFunction (const APIContext& ctx, tcu::TestLog& log, const char* const name, deBool shouldBeNonNull, deUint32& failsQuantity)
387 if ((ctx.getInstanceProcAddr(ctx.instance, name) == DE_NULL) == shouldBeNonNull)
388 reportFail(log, "vkGetInstanceProcAddr", "instance", name, shouldBeNonNull, failsQuantity);
391 void checkDeviceFunction (const APIContext& ctx, tcu::TestLog& log, const char* const name, deBool shouldBeNonNull, deUint32& failsQuantity)
393 if ((ctx.getDeviceProcAddr(ctx.device, name) == DE_NULL) == shouldBeNonNull)
394 reportFail(log, "vkGetDeviceProcAddr", "device", name, shouldBeNonNull, failsQuantity);
397 deBool isSupportedInstanceExt (const string extName, const deUint32 apiVersion)
399 const vector<string> supportedInstanceExtensions (getSupportedInstanceExtensions(apiVersion));
401 return de::contains(supportedInstanceExtensions.begin(), supportedInstanceExtensions.end(), extName);
404 deBool isSupportedDeviceExt (const string extName, const deUint32 apiVersion)
406 const vector<string> supportedDeviceExtensions (getSupportedDeviceExtensions(apiVersion));
408 return de::contains(supportedDeviceExtensions.begin(), supportedDeviceExtensions.end(), extName);
411 deBool mixupAddressProcCheck (const APIContext& ctx, tcu::TestLog& log, deUint32& failsQuantity, const vector<pair<const char*, FunctionOrigin> >& testsArr)
413 const deUint32 startingQuantity = failsQuantity;
414 for (deUint32 ndx = 0u; ndx < testsArr.size(); ++ndx)
416 if (deStringEqual(testsArr[ndx].first, "vkGetInstanceProcAddr") || deStringEqual(testsArr[ndx].first, "vkEnumerateInstanceVersion"))
419 const char* functionName = testsArr[ndx].first;
420 const deUint32 functionType = testsArr[ndx].second;
421 if (functionType == FUNCTIONORIGIN_INSTANCE)
423 checkPlatformFunction(ctx, log, functionName, DE_FALSE, failsQuantity);
424 checkDeviceFunction(ctx, log, functionName, DE_FALSE, failsQuantity);
426 else if (functionType == FUNCTIONORIGIN_DEVICE)
427 checkPlatformFunction(ctx, log, functionName, DE_FALSE, failsQuantity);
429 return startingQuantity == failsQuantity;
432 deBool specialCasesCheck (const APIContext& ctx, tcu::TestLog& log, deUint32& failsQuantity, const vector<pair<const char*, FunctionOrigin> >& testsArr)
434 const deUint32 startingQuantity = failsQuantity;
435 for (deUint32 ndx = 0u; ndx < testsArr.size(); ++ndx)
437 const deUint32 functionType = testsArr[ndx].second;
438 if (functionType == FUNCTIONORIGIN_PLATFORM)
439 checkPlatformFunction(ctx, log, testsArr[ndx].first, DE_FALSE, failsQuantity);
440 else if (functionType == FUNCTIONORIGIN_INSTANCE)
441 checkInstanceFunction(ctx, log, testsArr[ndx].first, DE_FALSE, failsQuantity);
442 else if (functionType == FUNCTIONORIGIN_DEVICE)
443 checkDeviceFunction(ctx, log, testsArr[ndx].first, DE_FALSE, failsQuantity);
445 return startingQuantity == failsQuantity;
448 deBool regularCheck (const APIContext& ctx, tcu::TestLog& log, deUint32& failsQuantity, const vector<pair<const char*, FunctionOrigin> >& testsArr)
450 const deUint32 startingQuantity = failsQuantity;
451 for (deUint32 ndx = 0u; ndx < testsArr.size(); ++ndx)
453 if (deStringEqual(testsArr[ndx].first, "vkGetInstanceProcAddr") && m_context.getUsedApiVersion() < VK_API_VERSION_1_2)
456 const deUint32 functionType = testsArr[ndx].second;
457 if (functionType == FUNCTIONORIGIN_PLATFORM)
458 checkPlatformFunction(ctx, log, testsArr[ndx].first, DE_TRUE, failsQuantity);
459 else if (functionType == FUNCTIONORIGIN_INSTANCE)
461 checkInstanceFunction(ctx, log, testsArr[ndx].first, DE_TRUE, failsQuantity);
462 checkDeviceFunction(ctx, log, testsArr[ndx].first, DE_FALSE, failsQuantity);
464 else if (functionType == FUNCTIONORIGIN_DEVICE)
466 checkInstanceFunction(ctx, log, testsArr[ndx].first, DE_TRUE, failsQuantity);
467 checkDeviceFunction(ctx, log, testsArr[ndx].first, DE_TRUE, failsQuantity);
470 return startingQuantity == failsQuantity;
474 class APIEntryPointsTestCase : public TestCase
477 APIEntryPointsTestCase (tcu::TestContext& testCtx)
478 : TestCase (testCtx, "entry_points", "Prints out API info.")
481 virtual ~APIEntryPointsTestCase (void)
483 virtual TestInstance* createInstance (Context& ctx) const
485 return new APIEntryPointsTestInstance(ctx);
493 tcu::TestCaseGroup* createVersionSanityCheckTests (tcu::TestContext & testCtx)
495 de::MovePtr<tcu::TestCaseGroup> versionTests (new tcu::TestCaseGroup(testCtx, "version_check", "API Version Tests"));
496 versionTests->addChild(new APIVersionTestCase(testCtx));
497 versionTests->addChild(new APIEntryPointsTestCase(testCtx));
498 return versionTests.release();