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