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 // The invalid param value and valid tests need to use vendor-specific application
142 // parameter keys and values. In order to have full test coverage, vendors should
143 // provide their own test data for the invalid param value and valid tests here.
144 //
145 #if defined(VENDOR_PARAMS_ADDED)
146 {{INSTANCE, INVALID_PARAM_VALUE},
147 validVendorID,
148 validDeviceID,
149 validInstanceParamKey,
150 invalidInstanceParamValue,
151 VK_ERROR_INITIALIZATION_FAILED},
152 {{INSTANCE, VALID}, validVendorID, validDeviceID, validInstanceParamKey, validInstanceParamValue, VK_SUCCESS},
153 {{DEVICE, INVALID_PARAM_VALUE},
154 validVendorID,
155 validDeviceID,
156 validDeviceParamKey,
157 invalidDeviceParamValue,
158 VK_ERROR_INITIALIZATION_FAILED},
159 {{DEVICE, VALID}, validVendorID, validDeviceID, validDeviceParamKey, validDeviceParamValue, VK_SUCCESS}
160 #endif // defined(VENDOR_PARAMS_ADDED)
161 };
162
163 if (testParams.testType != INVALID_PARAM_VALUE && testParams.testType != VALID)
164 testDataList.push_back(getDefaultTestData(context, testParams));
165
166 for (TestData vendorTestData : vendorTestDataList)
167 {
168 if (vendorTestData.testParams.createType == testParams.createType &&
169 vendorTestData.testParams.testType == testParams.testType && vendorTestData.vendorId == vendorId &&
170 (vendorTestData.deviceId == 0 || vendorTestData.deviceId == deviceId))
171 {
172 testDataList.push_back(vendorTestData);
173 }
174 }
175
176 return testDataList;
177 }
178
checkSupport(Context & context,TestParams testParams)179 void checkSupport(Context &context, TestParams testParams)
180 {
181 const std::vector<VkExtensionProperties> supportedExtensions =
182 enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL);
183
184 if (!isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_EXT_application_parameters")))
185 TCU_THROW(NotSupportedError, "VK_EXT_application_parameters is not supported");
186
187 const std::vector<TestData> testDataList = getTestDataList(context, testParams);
188
189 if (testDataList.empty())
190 TCU_THROW(TestError, "No test data available - please update vendorTestDataList");
191 }
192
createDeviceTest(Context & context,TestParams testParams)193 tcu::TestStatus createDeviceTest(Context &context, TestParams testParams)
194 {
195 tcu::TestLog &log = context.getTestContext().getLog();
196 const PlatformInterface &platformInterface = context.getPlatformInterface();
197 const CustomInstance instance(createCustomInstanceFromContext(context));
198 const InstanceDriver &instanceDriver(instance.getDriver());
199 const VkPhysicalDevice physicalDevice =
200 chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
201 const std::vector<TestData> testDataList = getTestDataList(context, testParams);
202 const float queuePriority = 1.0f;
203 VkDeviceObjectReservationCreateInfo devObjectResCreateInfo = resetDeviceObjectReservationCreateInfo();
204 bool testPassed = true;
205 const VkPhysicalDeviceVulkanSC10Features sc10Features = {
206 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_SC_1_0_FEATURES, // sType;
207 &devObjectResCreateInfo, // pNext;
208 VK_FALSE // shaderAtomicInstructions;
209 };
210
211 for (TestData testData : testDataList)
212 {
213 const VkApplicationParametersEXT appParams = {VK_STRUCTURE_TYPE_APPLICATION_PARAMETERS_EXT,
214 &sc10Features,
215 testData.vendorId,
216 testData.deviceId,
217 testData.paramKey,
218 testData.paramValue};
219
220 const VkDeviceQueueCreateInfo deviceQueueCreateInfo = {
221 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
222 DE_NULL, // pNext
223 (VkDeviceQueueCreateFlags)0u, // flags
224 0, // queueFamilyIndex;
225 1, // queueCount;
226 &queuePriority, // pQueuePriorities;
227 };
228
229 VkDeviceCreateInfo deviceCreateInfo = {
230 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType;
231 &appParams, // pNext;
232 (VkDeviceCreateFlags)0u, // flags
233 1, // queueRecordCount;
234 &deviceQueueCreateInfo, // pRequestedQueues;
235 0, // layerCount;
236 DE_NULL, // ppEnabledLayerNames;
237 0, // extensionCount;
238 DE_NULL, // ppEnabledExtensionNames;
239 DE_NULL, // pEnabledFeatures;
240 };
241
242 log << tcu::TestLog::Message << "Creating device with application parameters: " << appParams
243 << tcu::TestLog::EndMessage;
244
245 VkDevice device = (VkDevice)0;
246 const VkResult result = instanceDriver.createDevice(physicalDevice, &deviceCreateInfo, DE_NULL, &device);
247
248 if (device)
249 {
250 const DeviceDriver deviceIface(platformInterface, instance, device, context.getUsedApiVersion(),
251 context.getTestContext().getCommandLine());
252 deviceIface.destroyDevice(device, DE_NULL /*pAllocator*/);
253 }
254
255 log << tcu::TestLog::Message
256 << "Device creation returned with " + de::toString(getResultName(result)) + " (expecting " +
257 de::toString(getResultName(testData.expectedResult)) + ")"
258 << tcu::TestLog::EndMessage;
259
260 if (result != testData.expectedResult)
261 testPassed = false;
262 }
263
264 if (testPassed)
265 return tcu::TestStatus::pass("Pass");
266 else
267 return tcu::TestStatus::fail("Fail");
268 }
269
createInstanceTest(Context & context,TestParams testParams)270 tcu::TestStatus createInstanceTest(Context &context, TestParams testParams)
271 {
272 tcu::TestLog &log = context.getTestContext().getLog();
273 const PlatformInterface &platformInterface = context.getPlatformInterface();
274 const std::vector<TestData> testDataList = getTestDataList(context, testParams);
275 bool testPassed = true;
276
277 for (TestData testData : testDataList)
278 {
279 const VkApplicationParametersEXT appParams{VK_STRUCTURE_TYPE_APPLICATION_PARAMETERS_EXT,
280 DE_NULL,
281 testData.vendorId,
282 testData.deviceId,
283 testData.paramKey,
284 testData.paramValue};
285
286 const VkApplicationInfo appInfo = {
287 VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType;
288 &appParams, // const void* pNext;
289 "appName", // const char* pAppName;
290 0u, // uint32_t appVersion;
291 "engineName", // const char* pEngineName;
292 0u, // uint32_t engineVersion;
293 context.getUsedApiVersion(), // uint32_t apiVersion;
294 };
295
296 const VkInstanceCreateInfo instanceCreateInfo = {
297 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType;
298 DE_NULL, // const void* pNext;
299 (VkInstanceCreateFlags)0u, // VkInstanceCreateFlags flags;
300 &appInfo, // const VkApplicationInfo* pAppInfo;
301 0u, // uint32_t layerCount;
302 DE_NULL, // const char*const* ppEnabledLayernames;
303 0u, // uint32_t extensionCount;
304 DE_NULL, // const char*const* ppEnabledExtensionNames;
305 };
306
307 log << tcu::TestLog::Message << "Creating instance with application parameters: " << appParams
308 << tcu::TestLog::EndMessage;
309
310 VkInstance instance = (VkInstance)0;
311 const VkResult result =
312 platformInterface.createInstance(&instanceCreateInfo, DE_NULL /*pAllocator*/, &instance);
313
314 if (instance)
315 {
316 const InstanceDriver instanceIface(platformInterface, instance);
317 instanceIface.destroyInstance(instance, DE_NULL /*pAllocator*/);
318 }
319
320 log << tcu::TestLog::Message
321 << "Instance creation returned with " + de::toString(getResultName(result)) + " (expecting " +
322 de::toString(getResultName(testData.expectedResult)) + ")"
323 << tcu::TestLog::EndMessage;
324
325 if (result != testData.expectedResult)
326 testPassed = false;
327 }
328
329 if (testPassed)
330 return tcu::TestStatus::pass("Pass");
331 else
332 return tcu::TestStatus::fail("Fail");
333 }
334
createApplicationParametersTests(tcu::TestContext & testCtx)335 tcu::TestCaseGroup *createApplicationParametersTests(tcu::TestContext &testCtx)
336 {
337 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "application_parameters"));
338
339 const struct
340 {
341 ApplicationParametersCreateType createType;
342 const char *name;
343 } groups[2] = {{INSTANCE, "create_instance"}, {DEVICE, "create_device"}};
344
345 const struct
346 {
347 ApplicationParametersTestType testType;
348 const char *name;
349 } tests[5] = {{INVALID_VENDOR_ID, "invalid_vendor_id"},
350 {INVALID_DEVICE_ID, "invalid_device_id"},
351 {INVALID_PARAM_KEY, "invalid_parameter_key"},
352 {INVALID_PARAM_VALUE, "invalid_parameter_value"},
353 {VALID, "valid"}};
354
355 for (int groupIdx = 0; groupIdx < DE_LENGTH_OF_ARRAY(groups); ++groupIdx)
356 {
357 de::MovePtr<tcu::TestCaseGroup> createGroup(new tcu::TestCaseGroup(testCtx, groups[groupIdx].name));
358
359 for (int testIdx = 0; testIdx < DE_LENGTH_OF_ARRAY(tests); ++testIdx)
360 {
361 TestParams testParams = {groups[groupIdx].createType, tests[testIdx].testType};
362
363 if (testParams.createType == INSTANCE)
364 addFunctionCase(createGroup.get(), tests[testIdx].name, checkSupport, createInstanceTest, testParams);
365 else
366 addFunctionCase(createGroup.get(), tests[testIdx].name, checkSupport, createDeviceTest, testParams);
367 }
368
369 group->addChild(createGroup.release());
370 }
371
372 return group.release();
373 }
374
375 } // namespace sc
376
377 } // namespace vkt
378