1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2022 NVIDIA CORPORATION, Inc.
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 Vulkan SC VK_EXT_application_parameters Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktApplicationParametersTests.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27 #include "vktCustomInstancesDevices.hpp"
28 #include "vkSafetyCriticalUtil.hpp"
29 #include "vkDeviceUtil.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "tcuTestLog.hpp"
32
33 namespace vkt
34 {
35 namespace sc
36 {
37
38 using namespace vk;
39
40 enum ApplicationParametersCreateType
41 {
42 INSTANCE = 0,
43 DEVICE
44 };
45
46 enum ApplicationParametersTestType
47 {
48 INVALID_VENDOR_ID = 0,
49 INVALID_DEVICE_ID,
50 INVALID_PARAM_KEY,
51 INVALID_PARAM_VALUE,
52 VALID
53 };
54
55 struct TestParams
56 {
57 ApplicationParametersCreateType createType;
58 ApplicationParametersTestType testType;
59 };
60
61 struct TestData
62 {
63 TestParams testParams;
64 uint32_t vendorId;
65 uint32_t deviceId;
66 uint32_t paramKey;
67 uint64_t paramValue;
68 VkResult expectedResult;
69 };
70
readIDsFromDevice(Context & context,uint32_t & vendorId,uint32_t & deviceId)71 void readIDsFromDevice (Context& context, uint32_t& vendorId, uint32_t& deviceId)
72 {
73 const InstanceInterface& instanceInterface = context.getInstanceInterface();
74 VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
75 VkPhysicalDeviceProperties properties;
76
77 instanceInterface.getPhysicalDeviceProperties(physicalDevice, &properties);
78
79 vendorId = properties.vendorID;
80 deviceId = properties.deviceID;
81 }
82
getDefaultTestData(Context & context,TestParams testParams)83 TestData getDefaultTestData (Context& context, TestParams testParams)
84 {
85 TestData testData{};
86 testData.testParams = testParams;
87
88 readIDsFromDevice(context, testData.vendorId, testData.deviceId);
89
90 switch(testParams.testType)
91 {
92 case INVALID_VENDOR_ID:
93 testData.vendorId = 0x01234567;
94 testData.expectedResult = VK_ERROR_INCOMPATIBLE_DRIVER;
95 break;
96
97 case INVALID_DEVICE_ID:
98 testData.deviceId = 0x01234567;
99 testData.expectedResult = VK_ERROR_INCOMPATIBLE_DRIVER;
100 break;
101
102 case INVALID_PARAM_KEY:
103 testData.paramKey = 0x7fffffff;
104 testData.expectedResult = VK_ERROR_INITIALIZATION_FAILED;
105 break;
106
107 case INVALID_PARAM_VALUE:
108 case VALID:
109 // There is no default test case for the invalid param value and valid tests.
110 // Vendors should provide their own test data for these tests in getTestDataList.
111 break;
112 }
113
114 if (testParams.createType == DEVICE && testParams.testType != VALID)
115 testData.expectedResult = VK_ERROR_INITIALIZATION_FAILED;
116
117 return testData;
118 }
119
getTestDataList(Context & context,TestParams testParams)120 std::vector<TestData> getTestDataList(Context& context, TestParams testParams)
121 {
122 std::vector<TestData> testDataList;
123 uint32_t vendorId;
124 uint32_t deviceId;
125
126 readIDsFromDevice(context, vendorId, deviceId);
127
128 //#define VENDOR_PARAMS_ADDED 1
129 #if defined(VENDOR_PARAMS_ADDED)
130 uint32_t validVendorID = vendorId;
131 uint32_t validDeviceID = deviceId;
132 uint32_t validInstanceParamKey = 0; // TODO: provide valid instance parameter key
133 uint64_t invalidInstanceParamValue = 0; // TODO: provide invalid parameter value for <validInstanceParamKey>
134 uint64_t validInstanceParamValue = 0; // TODO: provide valid parameter value for <validInstanceParamKey>
135 uint32_t validDeviceParamKey = 0; // TODO: provide valid device parameter key
136 uint64_t invalidDeviceParamValue = 0; // TODO: provide invalid parameter value for <validDeviceParamKey>
137 uint64_t validDeviceParamValue = 0; // TODO: provide valid parameter value for <validDeviceParamKey>
138 #endif
139
140 const std::vector<TestData> vendorTestDataList =
141 {
142 // The invalid param value and valid tests need to use vendor-specific application
143 // parameter keys and values. In order to have full test coverage, vendors should
144 // provide their own test data for the invalid param value and valid tests here.
145 //
146 #if defined(VENDOR_PARAMS_ADDED)
147 {
148 { INSTANCE, INVALID_PARAM_VALUE },
149 validVendorID,
150 validDeviceID,
151 validInstanceParamKey,
152 invalidInstanceParamValue,
153 VK_ERROR_INITIALIZATION_FAILED
154 },
155 {
156 { INSTANCE, VALID },
157 validVendorID,
158 validDeviceID,
159 validInstanceParamKey,
160 validInstanceParamValue,
161 VK_SUCCESS
162 },
163 {
164 { DEVICE, INVALID_PARAM_VALUE },
165 validVendorID,
166 validDeviceID,
167 validDeviceParamKey,
168 invalidDeviceParamValue,
169 VK_ERROR_INITIALIZATION_FAILED
170 },
171 {
172 { DEVICE, VALID },
173 validVendorID,
174 validDeviceID,
175 validDeviceParamKey,
176 validDeviceParamValue,
177 VK_SUCCESS
178 }
179 #endif // defined(VENDOR_PARAMS_ADDED)
180 };
181
182 if (testParams.testType != INVALID_PARAM_VALUE && testParams.testType != VALID)
183 testDataList.push_back(getDefaultTestData(context, testParams));
184
185 for (TestData vendorTestData : vendorTestDataList)
186 {
187 if (vendorTestData.testParams.createType == testParams.createType &&
188 vendorTestData.testParams.testType == testParams.testType &&
189 vendorTestData.vendorId == vendorId &&
190 (vendorTestData.deviceId == 0 || vendorTestData.deviceId == deviceId))
191 {
192 testDataList.push_back(vendorTestData);
193 }
194 }
195
196 return testDataList;
197 }
198
checkSupport(Context & context,TestParams testParams)199 void checkSupport (Context& context, TestParams testParams)
200 {
201 const std::vector<VkExtensionProperties> supportedExtensions = enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL);
202
203 if (!isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_EXT_application_parameters")))
204 TCU_THROW(NotSupportedError, "VK_EXT_application_parameters is not supported");
205
206 const std::vector<TestData> testDataList = getTestDataList(context, testParams);
207
208 if (testDataList.empty())
209 TCU_THROW(TestError, "No test data available - please update vendorTestDataList");
210 }
211
createDeviceTest(Context & context,TestParams testParams)212 tcu::TestStatus createDeviceTest (Context& context, TestParams testParams)
213 {
214 tcu::TestLog& log = context.getTestContext().getLog();
215 const PlatformInterface& platformInterface = context.getPlatformInterface();
216 const CustomInstance instance (createCustomInstanceFromContext(context));
217 const InstanceDriver& instanceDriver (instance.getDriver());
218 const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
219 const std::vector<TestData> testDataList = getTestDataList(context, testParams);
220 const float queuePriority = 1.0f;
221 VkDeviceObjectReservationCreateInfo devObjectResCreateInfo = resetDeviceObjectReservationCreateInfo();
222 bool testPassed = true;
223 const VkPhysicalDeviceVulkanSC10Features sc10Features =
224 {
225 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_SC_1_0_FEATURES, // sType;
226 &devObjectResCreateInfo, // pNext;
227 VK_FALSE // shaderAtomicInstructions;
228 };
229
230 for (TestData testData : testDataList)
231 {
232 const VkApplicationParametersEXT appParams =
233 {
234 VK_STRUCTURE_TYPE_APPLICATION_PARAMETERS_EXT,
235 &sc10Features,
236 testData.vendorId,
237 testData.deviceId,
238 testData.paramKey,
239 testData.paramValue
240 };
241
242 const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
243 {
244 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
245 DE_NULL, // pNext
246 (VkDeviceQueueCreateFlags)0u, // flags
247 0, // queueFamilyIndex;
248 1, // queueCount;
249 &queuePriority, // pQueuePriorities;
250 };
251
252 VkDeviceCreateInfo deviceCreateInfo =
253 {
254 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType;
255 &appParams, // pNext;
256 (VkDeviceCreateFlags)0u, // flags
257 1, // queueRecordCount;
258 &deviceQueueCreateInfo, // pRequestedQueues;
259 0, // layerCount;
260 DE_NULL, // ppEnabledLayerNames;
261 0, // extensionCount;
262 DE_NULL, // ppEnabledExtensionNames;
263 DE_NULL, // pEnabledFeatures;
264 };
265
266 log << tcu::TestLog::Message << "Creating device with application parameters: " << appParams << tcu::TestLog::EndMessage;
267
268 VkDevice device = (VkDevice)0;
269 const VkResult result = instanceDriver.createDevice(physicalDevice, &deviceCreateInfo, DE_NULL, &device);
270
271 if (device)
272 {
273 const DeviceDriver deviceIface(platformInterface, instance, device);
274 deviceIface.destroyDevice(device, DE_NULL/*pAllocator*/);
275 }
276
277 log << tcu::TestLog::Message << "Device creation returned with " + de::toString(getResultName(result)) +
278 " (expecting " + de::toString(getResultName(testData.expectedResult)) + ")" << tcu::TestLog::EndMessage;
279
280 if (result != testData.expectedResult)
281 testPassed = false;
282 }
283
284 if (testPassed)
285 return tcu::TestStatus::pass("Pass");
286 else
287 return tcu::TestStatus::fail("Fail");
288 }
289
createInstanceTest(Context & context,TestParams testParams)290 tcu::TestStatus createInstanceTest (Context& context, TestParams testParams)
291 {
292 tcu::TestLog& log = context.getTestContext().getLog();
293 const PlatformInterface& platformInterface = context.getPlatformInterface();
294 const std::vector<TestData> testDataList = getTestDataList(context, testParams);
295 bool testPassed = true;
296
297 for (TestData testData : testDataList)
298 {
299 const VkApplicationParametersEXT appParams
300 {
301 VK_STRUCTURE_TYPE_APPLICATION_PARAMETERS_EXT,
302 DE_NULL,
303 testData.vendorId,
304 testData.deviceId,
305 testData.paramKey,
306 testData.paramValue
307 };
308
309 const VkApplicationInfo appInfo =
310 {
311 VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType;
312 &appParams, // const void* pNext;
313 "appName", // const char* pAppName;
314 0u, // deUint32 appVersion;
315 "engineName", // const char* pEngineName;
316 0u, // deUint32 engineVersion;
317 context.getUsedApiVersion(), // deUint32 apiVersion;
318 };
319
320 const VkInstanceCreateInfo instanceCreateInfo =
321 {
322 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType;
323 DE_NULL, // const void* pNext;
324 (VkInstanceCreateFlags)0u, // VkInstanceCreateFlags flags;
325 &appInfo, // const VkApplicationInfo* pAppInfo;
326 0u, // deUint32 layerCount;
327 DE_NULL, // const char*const* ppEnabledLayernames;
328 0u, // deUint32 extensionCount;
329 DE_NULL, // const char*const* ppEnabledExtensionNames;
330 };
331
332 log << tcu::TestLog::Message << "Creating instance with application parameters: " << appParams << tcu::TestLog::EndMessage;
333
334 VkInstance instance = (VkInstance)0;
335 const VkResult result = platformInterface.createInstance(&instanceCreateInfo, DE_NULL/*pAllocator*/, &instance);
336
337 if (instance)
338 {
339 const InstanceDriver instanceIface(platformInterface, instance);
340 instanceIface.destroyInstance(instance, DE_NULL/*pAllocator*/);
341 }
342
343 log << tcu::TestLog::Message << "Instance creation returned with " + de::toString(getResultName(result)) +
344 " (expecting " + de::toString(getResultName(testData.expectedResult)) + ")" << tcu::TestLog::EndMessage;
345
346 if (result != testData.expectedResult)
347 testPassed = false;
348 }
349
350 if (testPassed)
351 return tcu::TestStatus::pass("Pass");
352 else
353 return tcu::TestStatus::fail("Fail");
354 }
355
createApplicationParametersTests(tcu::TestContext & testCtx)356 tcu::TestCaseGroup* createApplicationParametersTests (tcu::TestContext& testCtx)
357 {
358 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "application_parameters", "Tests VK_EXT_application_parameters"));
359
360 const struct
361 {
362 ApplicationParametersCreateType createType;
363 const char* name;
364 } groups[2] =
365 {
366 { INSTANCE, "create_instance" },
367 { DEVICE, "create_device" }
368 };
369
370 const struct
371 {
372 ApplicationParametersTestType testType;
373 const char* name;
374 } tests[5] =
375 {
376 { INVALID_VENDOR_ID, "invalid_vendor_id" },
377 { INVALID_DEVICE_ID, "invalid_device_id" },
378 { INVALID_PARAM_KEY, "invalid_parameter_key" },
379 { INVALID_PARAM_VALUE, "invalid_parameter_value" },
380 { VALID, "valid" }
381 };
382
383 for (int groupIdx = 0; groupIdx < DE_LENGTH_OF_ARRAY(groups); ++groupIdx)
384 {
385 de::MovePtr<tcu::TestCaseGroup> createGroup(new tcu::TestCaseGroup(testCtx, groups[groupIdx].name, ""));
386
387 for (int testIdx = 0; testIdx < DE_LENGTH_OF_ARRAY(tests); ++testIdx)
388 {
389 TestParams testParams = { groups[groupIdx].createType, tests[testIdx].testType };
390
391 if (testParams.createType == INSTANCE)
392 addFunctionCase(createGroup.get(), tests[testIdx].name, "", checkSupport, createInstanceTest, testParams);
393 else
394 addFunctionCase(createGroup.get(), tests[testIdx].name, "", checkSupport, createDeviceTest, testParams);
395 }
396
397 group->addChild(createGroup.release());
398 }
399
400 return group.release();
401 }
402
403 } // sc
404
405 } // vkt
406