1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 Khronos Group
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief API Version Check test - prints out version info
22 *//*--------------------------------------------------------------------*/
23
24 #include <iostream>
25 #include <typeinfo>
26
27 #include "tcuDefs.hpp"
28 #include "tcuTestCase.hpp"
29 #include "tcuTestLog.hpp"
30 #include "tcuFunctionLibrary.hpp"
31 #include "tcuPlatform.hpp"
32
33 #include "vkApiVersion.hpp"
34 #include "vkDefs.hpp"
35 #include "vkPlatform.hpp"
36
37 #include "vktApiVersionCheck.hpp"
38 #include "vktTestCase.hpp"
39
40 #include "vkRefUtil.hpp"
41 #include "vkDeviceUtil.hpp"
42
43 #include "deString.h"
44 #include "deStringUtil.hpp"
45
46 #include <map>
47 #include <vector>
48
49 using namespace vk;
50 using namespace std;
51
52 namespace vkt
53 {
54
55 namespace api
56 {
57
58 namespace
59 {
60
61 #include "vkCoreFunctionalities.inl"
62
63 class APIVersionTestInstance : public TestInstance
64 {
65 public:
APIVersionTestInstance(Context & ctx)66 APIVersionTestInstance (Context& ctx)
67 : TestInstance (ctx)
68 {}
iterate(void)69 virtual tcu::TestStatus iterate (void)
70 {
71 tcu::TestLog& log = m_context.getTestContext().getLog();
72 const vk::ApiVersion instanceVersion = vk::unpackVersion(m_context.getAvailableInstanceVersion());
73 const vk::ApiVersion deviceVersion = vk::unpackVersion(m_context.getDeviceVersion());
74 const vk::ApiVersion usedApiVersion = vk::unpackVersion(m_context.getUsedApiVersion());
75
76 log << tcu::TestLog::Message << "availableInstanceVersion: " << instanceVersion << tcu::TestLog::EndMessage;
77 log << tcu::TestLog::Message << "deviceVersion: " << deviceVersion << tcu::TestLog::EndMessage;
78 log << tcu::TestLog::Message << "usedApiVersion: " << usedApiVersion << tcu::TestLog::EndMessage;
79 const ::std::string result = de::toString(usedApiVersion.majorNum) + ::std::string(".") + de::toString(usedApiVersion.minorNum) + ::std::string(".") + de::toString(usedApiVersion.patchNum);
80 return tcu::TestStatus::pass(result);
81 }
82 };
83
84 class APIVersionTestCase : public TestCase
85 {
86 public:
APIVersionTestCase(tcu::TestContext & testCtx)87 APIVersionTestCase (tcu::TestContext& testCtx)
88 : TestCase (testCtx, "version", "Prints out API info.")
89 {}
90
~APIVersionTestCase(void)91 virtual ~APIVersionTestCase (void)
92 {}
createInstance(Context & ctx) const93 virtual TestInstance* createInstance (Context& ctx) const
94 {
95 return new APIVersionTestInstance(ctx);
96 }
97
98 private:
99 };
100
101 class APIEntryPointsTestInstance : public TestInstance
102 {
103 public:
APIEntryPointsTestInstance(Context & ctx)104 APIEntryPointsTestInstance (Context& ctx)
105 : TestInstance (ctx)
106 {
107
108 }
iterate(void)109 virtual tcu::TestStatus iterate (void)
110 {
111 tcu::TestLog& log = m_context.getTestContext().getLog();
112 const vk::Platform& platform = m_context.getTestContext().getPlatform().getVulkanPlatform();
113 de::MovePtr<vk::Library> vkLibrary = de::MovePtr<vk::Library>(platform.createLibrary());
114 const tcu::FunctionLibrary& funcLibrary = vkLibrary->getFunctionLibrary();
115 std::vector<std::string> empty = std::vector<std::string>();
116 instance = createDefaultInstance(m_context.getPlatformInterface(), m_context.getUsedApiVersion(), empty, empty, DE_NULL);
117 device = createTestDevice(m_context.getPlatformInterface(), m_context.getInstanceInterface(), m_context.getPhysicalDevice());
118 getInstanceProcAddr = reinterpret_cast<GetInstanceProcAddrFunc>(funcLibrary.getFunction("vkGetInstanceProcAddr"));
119 getDeviceProcAddr = reinterpret_cast<GetDeviceProcAddrFunc>(getInstanceProcAddr(*instance, "vkGetDeviceProcAddr"));
120
121 deUint32 failsQuantity = 0u;
122
123 {
124 ApisMap functions = ApisMap();
125 initApisMap(functions);
126 ApisMap::const_iterator lastGoodVersion = functions.begin();
127 const ApisMap::const_iterator versionsEnd = functions.end();
128 for (ApisMap::const_iterator it = lastGoodVersion; it != versionsEnd; ++it)
129 {
130 if (it->first <= m_context.getUsedApiVersion())
131 lastGoodVersion = it;
132 }
133
134 log << tcu::TestLog::Message << "Regular check - tries to get core functions from proper vkGet*ProcAddr." << tcu::TestLog::EndMessage;
135 const char* const regularResult = regularCheck(log, failsQuantity, lastGoodVersion->second) ? "Passed" : "Failed";
136 log << tcu::TestLog::Message << regularResult << tcu::TestLog::EndMessage;
137
138 log << tcu::TestLog::Message << "Cross check - tries to get core functions from improper vkGet*ProcAddr." << tcu::TestLog::EndMessage;
139 const char* const mixupResult = mixupAddressProcCheck(log, failsQuantity, lastGoodVersion->second) ? "Passed" : "Failed";
140 log << tcu::TestLog::Message << mixupResult << tcu::TestLog::EndMessage;
141 }
142
143 {
144 FunctionInfosList extFunctions = FunctionInfosList();
145 extFunctions.push_back(FunctionInfo("vkTrimCommandPoolKHR", FUNCTIONORIGIN_DEVICE));
146 extFunctions.push_back(FunctionInfo("vkCmdPushDescriptorSetKHR", FUNCTIONORIGIN_DEVICE));
147 extFunctions.push_back(FunctionInfo("vkCreateSamplerYcbcrConversionKHR", FUNCTIONORIGIN_DEVICE));
148 extFunctions.push_back(FunctionInfo("vkGetSwapchainStatusKHR", FUNCTIONORIGIN_DEVICE));
149 extFunctions.push_back(FunctionInfo("vkCreateSwapchainKHR", FUNCTIONORIGIN_DEVICE));
150 extFunctions.push_back(FunctionInfo("vkGetImageSparseMemoryRequirements2KHR", FUNCTIONORIGIN_DEVICE));
151 extFunctions.push_back(FunctionInfo("vkBindBufferMemory2KHR", FUNCTIONORIGIN_DEVICE));
152 extFunctions.push_back(FunctionInfo("vkImportFenceWin32HandleKHR", FUNCTIONORIGIN_DEVICE));
153 extFunctions.push_back(FunctionInfo("vkGetBufferMemoryRequirements2KHR", FUNCTIONORIGIN_DEVICE));
154 extFunctions.push_back(FunctionInfo("vkGetImageMemoryRequirements2KHR", FUNCTIONORIGIN_DEVICE));
155
156 log << tcu::TestLog::Message << "Extensions check - tries to get functions of disabled extensions from proper vkGet*ProcAddr." << tcu::TestLog::EndMessage;
157 const char * const result = specialCasesCheck(log, failsQuantity, extFunctions) ? "Passed" : "Failed";
158 log << tcu::TestLog::Message << result << tcu::TestLog::EndMessage;
159 }
160
161 {
162 FunctionInfosList dummyFunctions = FunctionInfosList();
163 for (deUint32 i = 0; i <= FUNCTIONORIGIN_DEVICE; ++i)
164 {
165 const FunctionOrigin origin = static_cast<FunctionOrigin>(i);
166 dummyFunctions.push_back(FunctionInfo("vkSomeName", origin));
167 dummyFunctions.push_back(FunctionInfo("vkNonexistingKHR", origin));
168 dummyFunctions.push_back(FunctionInfo("", origin));
169 }
170
171 log << tcu::TestLog::Message << "Special check - tries to get some dummy functions from various vkGet*ProcAddr." << tcu::TestLog::EndMessage;
172 const char * const result = specialCasesCheck(log, failsQuantity, dummyFunctions) ? "Passed" : "Failed";
173 log << tcu::TestLog::Message << result << tcu::TestLog::EndMessage;
174 }
175
176 if (failsQuantity > 0u)
177 return tcu::TestStatus::fail("Fail");
178 else
179 return tcu::TestStatus::pass("Pass");
180 }
181
182 private:
183
184 GetDeviceProcAddrFunc getDeviceProcAddr;
185 GetInstanceProcAddrFunc getInstanceProcAddr;
186 Move<VkInstance> instance;
187 Move<VkDevice> device;
188
findQueueFamilyIndex(const InstanceInterface & vkInstance,VkPhysicalDevice physicalDevice,VkQueueFlags requiredCaps)189 deUint32 findQueueFamilyIndex(const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
190 {
191 deUint32 numQueues = 0;
192 vkInstance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, DE_NULL);
193 if (numQueues > 0)
194 {
195 vector<VkQueueFamilyProperties> properties(numQueues);
196 vkInstance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueues, &properties[0]);
197 if (numQueues != static_cast<deUint32>(properties.size()))
198 TCU_FAIL("Returned queue family count changes between queries.");
199 for (deUint32 queueNdx = 0u; queueNdx < numQueues; queueNdx++)
200 if ((properties[queueNdx].queueFlags & requiredCaps) == requiredCaps)
201 return queueNdx;
202 }
203 TCU_FAIL("Returned queue family count was 0.");
204 return 0u;
205 }
206
createTestDevice(const PlatformInterface & vkp,const InstanceInterface & vki,VkPhysicalDevice physicalDevice)207 Move<VkDevice> createTestDevice (const PlatformInterface& vkp, const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
208 {
209 vector<string> enabledLayers;
210 vector<const char*> layerPtrs;
211 vector<const char*> extensionPtrs;
212 const float queuePriority = 1.0f;
213 const deUint32 queueIndex = findQueueFamilyIndex(vki, physicalDevice, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
214 VkDeviceQueueCreateInfo queueInfo = {
215 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
216 DE_NULL,
217 static_cast<VkDeviceQueueCreateFlags>(0u),
218 queueIndex,
219 1u,
220 &queuePriority
221 };
222 VkDeviceCreateInfo deviceInfo = {
223 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
224 DE_NULL,
225 static_cast<VkDeviceCreateFlags>(0u),
226 1u,
227 &queueInfo,
228 0u,
229 DE_NULL,
230 0u,
231 DE_NULL,
232 DE_NULL,
233 };
234 return vk::createDevice(vkp, *instance, vki, physicalDevice, &deviceInfo);
235 }
236
reportFail(tcu::TestLog & log,const char * const functionName,const char * const firstParamName,const char * const secondParamName,deBool shouldBeNonNull,deUint32 & failsQuantity)237 void reportFail (tcu::TestLog& log, const char* const functionName, const char* const firstParamName, const char* const secondParamName, deBool shouldBeNonNull, deUint32& failsQuantity)
238 {
239 log << tcu::TestLog::Message
240 << "[" << failsQuantity << "] " << functionName << '(' << firstParamName << ", \"" << secondParamName << "\") "
241 << "returned " << (shouldBeNonNull ? "nullptr" : "non-null") << " should return " << (shouldBeNonNull ? "valid function address" : "nullptr")
242 << tcu::TestLog::EndMessage;
243 ++failsQuantity;
244 }
245
checkPlatformFunction(tcu::TestLog & log,const char * const name,deBool shouldBeNonNull,deUint32 & failsQuantity)246 void checkPlatformFunction (tcu::TestLog& log, const char* const name, deBool shouldBeNonNull, deUint32& failsQuantity)
247 {
248 if ((getInstanceProcAddr(DE_NULL, name) == DE_NULL) == shouldBeNonNull)
249 reportFail(log, "vkGetInstanceProcAddr", "DE_NULL", name, shouldBeNonNull, failsQuantity);
250 }
251
checkInstanceFunction(tcu::TestLog & log,const char * const name,deBool shouldBeNonNull,deUint32 & failsQuantity)252 void checkInstanceFunction (tcu::TestLog& log, const char* const name, deBool shouldBeNonNull, deUint32& failsQuantity)
253 {
254 if ((getInstanceProcAddr(*instance, name) == DE_NULL) == shouldBeNonNull)
255 reportFail(log, "vkGetInstanceProcAddr", "instance", name, shouldBeNonNull, failsQuantity);
256 }
257
checkDeviceFunction(tcu::TestLog & log,const char * const name,deBool shouldBeNonNull,deUint32 & failsQuantity)258 void checkDeviceFunction (tcu::TestLog& log, const char* const name, deBool shouldBeNonNull, deUint32& failsQuantity)
259 {
260 if ((getDeviceProcAddr(*device, name) == DE_NULL) == shouldBeNonNull)
261 reportFail(log, "vkGetDeviceProcAddr", "device", name, shouldBeNonNull, failsQuantity);
262 }
263
mixupAddressProcCheck(tcu::TestLog & log,deUint32 & failsQuantity,const vector<pair<const char *,FunctionOrigin>> & testsArr)264 deBool mixupAddressProcCheck (tcu::TestLog& log, deUint32& failsQuantity, const vector<pair<const char*, FunctionOrigin> >& testsArr)
265 {
266 const deUint32 startingQuantity = failsQuantity;
267 for (deUint32 ndx = 0u; ndx < testsArr.size(); ++ndx)
268 {
269 if (deStringEqual(testsArr[ndx].first, "vkGetInstanceProcAddr") || deStringEqual(testsArr[ndx].first, "vkEnumerateInstanceVersion"))
270 continue;
271
272 const char* functionName = testsArr[ndx].first;
273 const deUint32 functionType = testsArr[ndx].second;
274 if (functionType == FUNCTIONORIGIN_INSTANCE)
275 {
276 checkPlatformFunction(log, functionName, DE_FALSE, failsQuantity);
277 checkDeviceFunction(log, functionName, DE_FALSE, failsQuantity);
278 }
279 else if (functionType == FUNCTIONORIGIN_DEVICE)
280 checkPlatformFunction(log, functionName, DE_FALSE, failsQuantity);
281 }
282 return startingQuantity == failsQuantity;
283 }
284
specialCasesCheck(tcu::TestLog & log,deUint32 & failsQuantity,const vector<pair<const char *,FunctionOrigin>> & testsArr)285 deBool specialCasesCheck (tcu::TestLog& log, deUint32& failsQuantity, const vector<pair<const char*, FunctionOrigin> >& testsArr)
286 {
287 const deUint32 startingQuantity = failsQuantity;
288 for (deUint32 ndx = 0u; ndx < testsArr.size(); ++ndx)
289 {
290 const deUint32 functionType = testsArr[ndx].second;
291 if (functionType == FUNCTIONORIGIN_PLATFORM)
292 checkPlatformFunction(log, testsArr[ndx].first, DE_FALSE, failsQuantity);
293 else if (functionType == FUNCTIONORIGIN_INSTANCE)
294 checkInstanceFunction(log, testsArr[ndx].first, DE_FALSE, failsQuantity);
295 else if (functionType == FUNCTIONORIGIN_DEVICE)
296 checkDeviceFunction(log, testsArr[ndx].first, DE_FALSE, failsQuantity);
297 }
298 return startingQuantity == failsQuantity;
299 }
300
regularCheck(tcu::TestLog & log,deUint32 & failsQuantity,const vector<pair<const char *,FunctionOrigin>> & testsArr)301 deBool regularCheck (tcu::TestLog& log, deUint32& failsQuantity, const vector<pair<const char*, FunctionOrigin> >& testsArr)
302 {
303 const deUint32 startingQuantity = failsQuantity;
304 for (deUint32 ndx = 0u; ndx < testsArr.size(); ++ndx)
305 {
306 if (deStringEqual(testsArr[ndx].first, "vkGetInstanceProcAddr") || deStringEqual(testsArr[ndx].first, "vkEnumerateInstanceVersion"))
307 continue;
308
309 const deUint32 functionType = testsArr[ndx].second;
310 if (functionType == FUNCTIONORIGIN_PLATFORM)
311 checkPlatformFunction(log, testsArr[ndx].first, DE_TRUE, failsQuantity);
312 else if (functionType == FUNCTIONORIGIN_INSTANCE)
313 checkInstanceFunction(log, testsArr[ndx].first, DE_TRUE, failsQuantity);
314 else if (functionType == FUNCTIONORIGIN_DEVICE)
315 checkDeviceFunction(log, testsArr[ndx].first, DE_TRUE, failsQuantity);
316 }
317 return startingQuantity == failsQuantity;
318 }
319 };
320
321 class APIEntryPointsTestCase : public TestCase
322 {
323 public:
APIEntryPointsTestCase(tcu::TestContext & testCtx)324 APIEntryPointsTestCase (tcu::TestContext& testCtx)
325 : TestCase (testCtx, "entry_points", "Prints out API info.")
326 {}
327
~APIEntryPointsTestCase(void)328 virtual ~APIEntryPointsTestCase (void)
329 {}
createInstance(Context & ctx) const330 virtual TestInstance* createInstance (Context& ctx) const
331 {
332 return new APIEntryPointsTestInstance(ctx);
333 }
334
335 private:
336 };
337
338 } // anonymous
339
createVersionSanityCheckTests(tcu::TestContext & testCtx)340 tcu::TestCaseGroup* createVersionSanityCheckTests (tcu::TestContext & testCtx)
341 {
342 de::MovePtr<tcu::TestCaseGroup> versionTests (new tcu::TestCaseGroup(testCtx, "version_check", "API Version Tests"));
343 versionTests->addChild(new APIVersionTestCase(testCtx));
344 versionTests->addChild(new APIEntryPointsTestCase(testCtx));
345 return versionTests.release();
346 }
347
348 } // api
349
350 } // vkt
351