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