1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 The Khronos Group 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 fault handling tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktFaultHandlingTests.hpp"
25
26 #include <set>
27 #include <vector>
28 #include <string>
29
30 #include "vktTestCaseUtil.hpp"
31 #include "vkDeviceUtil.hpp"
32 #include "vkSafetyCriticalUtil.hpp"
33 #include "vktCustomInstancesDevices.hpp"
34 #include "tcuTestLog.hpp"
35
36 namespace vkt
37 {
38 namespace sc
39 {
40
41 using namespace vk;
42
43 namespace
44 {
45
46 enum FHFaultValue
47 {
48 FHF_UNUSED = 0,
49 FHF_NULL,
50 FHF_ARRAY
51 };
52
53 struct TestParams
54 {
55 VkFaultQueryBehavior queryBehaviour;
56 FHFaultValue faultValue;
57 };
58
testGetFaultData(Context & context,TestParams testParams)59 tcu::TestStatus testGetFaultData (Context& context, TestParams testParams)
60 {
61 const DeviceInterface& vk = context.getDeviceInterface();
62 const VkDevice device = context.getDevice();
63
64 deUint32 maxQueryFaultCount = context.getDeviceVulkanSC10Properties().maxQueryFaultCount;
65
66 VkBool32 unrecordedFaults = VK_TRUE;
67 deUint32 faultCount = maxQueryFaultCount;
68 std::vector<VkFaultData> faults;
69 for (deUint32 i = 0; i < maxQueryFaultCount; ++i)
70 {
71 faults.push_back
72 (
73 {
74 VK_STRUCTURE_TYPE_FAULT_DATA, // VkStructureType sType;
75 DE_NULL, // void* pNext;
76 VK_FAULT_LEVEL_UNASSIGNED, // VkFaultLevel faultLevel;
77 VK_FAULT_TYPE_UNASSIGNED, // VkFaultType faultType;
78 }
79 );
80 }
81 bool isOK = true;
82 bool faultsModified = false;
83 VkResult result;
84
85 switch (testParams.faultValue)
86 {
87 case FHF_NULL:
88 result = vk.getFaultData(device, testParams.queryBehaviour, &unrecordedFaults, &faultCount, DE_NULL);
89
90 if (result != VK_SUCCESS)
91 {
92 context.getTestContext().getLog() << tcu::TestLog::Message << "Result is not VK_SUCCESS" << tcu::TestLog::EndMessage;
93 isOK = false;
94 }
95 if (unrecordedFaults != VK_FALSE)
96 {
97 context.getTestContext().getLog() << tcu::TestLog::Message << "unrecordedFaults is not VK_FALSE" << tcu::TestLog::EndMessage;
98 isOK = false;
99 }
100 if (faultCount != 0u)
101 {
102 context.getTestContext().getLog() << tcu::TestLog::Message << "faultCount is not 0" << tcu::TestLog::EndMessage;
103 isOK = false;
104 }
105 break;
106 case FHF_ARRAY:
107 result = vk.getFaultData(device, testParams.queryBehaviour, &unrecordedFaults, &faultCount, faults.data());
108
109 if (result != VK_SUCCESS)
110 {
111 context.getTestContext().getLog() << tcu::TestLog::Message << "Result is not VK_SUCCESS" << tcu::TestLog::EndMessage;
112 isOK = false;
113 }
114 if (unrecordedFaults != VK_FALSE)
115 {
116 context.getTestContext().getLog() << tcu::TestLog::Message << "unrecordedFaults is not VK_FALSE" << tcu::TestLog::EndMessage;
117 isOK = false;
118 }
119 if (faultCount != 0u)
120 {
121 context.getTestContext().getLog() << tcu::TestLog::Message << "faultCount is not 0" << tcu::TestLog::EndMessage;
122 isOK = false;
123 }
124 for (deUint32 i = 0; i < maxQueryFaultCount; ++i)
125 if (faults[i].faultLevel != VK_FAULT_LEVEL_UNASSIGNED || faults[i].faultType != VK_FAULT_TYPE_UNASSIGNED)
126 faultsModified = true;
127 if (faultsModified)
128 {
129 context.getTestContext().getLog() << tcu::TestLog::Message << "pFaults have been modified" << tcu::TestLog::EndMessage;
130 isOK = false;
131 }
132 break;
133 default:
134 TCU_THROW(InternalError, "Unrecognized fault type");
135 }
136
137 return isOK ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
138 }
139
testFaultCallback(VkBool32 incompleteFaultData,deUint32 faultCount,VkFaultData * pFaultData)140 void testFaultCallback (VkBool32 incompleteFaultData,
141 deUint32 faultCount,
142 VkFaultData* pFaultData)
143 {
144 DE_UNREF(incompleteFaultData);
145 DE_UNREF(faultCount);
146 DE_UNREF(pFaultData);
147 }
148
149 struct FaultCallbackInfoTestParams
150 {
151 bool allocateFaultData;
152 };
153
testCreateDeviceWithFaultCallbackInfo(Context & context,FaultCallbackInfoTestParams testParams)154 tcu::TestStatus testCreateDeviceWithFaultCallbackInfo (Context& context, FaultCallbackInfoTestParams testParams)
155 {
156 const CustomInstance instance (createCustomInstanceFromContext(context));
157 const InstanceDriver& instanceDriver (instance.getDriver());
158 const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
159
160 void* pNext = DE_NULL;
161
162 VkDeviceObjectReservationCreateInfo memReservationInfo = context.getTestContext().getCommandLine().isSubProcess() ? context.getResourceInterface()->getStatMax() : resetDeviceObjectReservationCreateInfo();
163 memReservationInfo.pNext = pNext;
164 pNext = &memReservationInfo;
165
166 VkPhysicalDeviceVulkanSC10Features sc10Features = createDefaultSC10Features();
167 sc10Features.pNext = pNext;
168 pNext = &sc10Features;
169
170 // create VkFaultCallbackInfo
171 deUint32 maxQueryFaultCount = context.getDeviceVulkanSC10Properties().maxQueryFaultCount;
172 std::vector<VkFaultData> faults;
173
174 if (testParams.allocateFaultData)
175 {
176 for (deUint32 i = 0; i < maxQueryFaultCount; ++i)
177 {
178 faults.push_back
179 (
180 {
181 VK_STRUCTURE_TYPE_FAULT_DATA, // VkStructureType sType;
182 DE_NULL, // void* pNext;
183 VK_FAULT_LEVEL_UNASSIGNED, // VkFaultLevel faultLevel;
184 VK_FAULT_TYPE_UNASSIGNED, // VkFaultType faultType;
185 }
186 );
187 }
188 }
189
190 VkFaultCallbackInfo faultCallBackInfo =
191 {
192 VK_STRUCTURE_TYPE_FAULT_CALLBACK_INFO, // VkStructureType sType;
193 DE_NULL, // void* pNext;
194 deUint32(faults.size()), // uint32_t faultCount;
195 testParams.allocateFaultData ? faults.data() : nullptr, // VkFaultData* pFaults;
196 (PFN_vkFaultCallbackFunction) testFaultCallback // PFN_vkFaultCallbackFunction pfnFaultCallback;
197 };
198 faultCallBackInfo.pNext = pNext;
199 pNext = &faultCallBackInfo;
200
201 // create VkDeviceCreateInfo
202
203 const float queuePriority = 1.0f;
204
205 const VkDeviceQueueCreateInfo deviceQueueCI =
206 {
207 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
208 DE_NULL, // pNext
209 (VkDeviceQueueCreateFlags)0u, // flags
210 0, //queueFamilyIndex;
211 1, //queueCount;
212 &queuePriority, //pQueuePriorities;
213 };
214
215 VkDeviceCreateInfo deviceCreateInfo =
216 {
217 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType;
218 pNext, // pNext;
219 (VkDeviceCreateFlags)0u, // flags
220 1, // queueRecordCount;
221 &deviceQueueCI, // pRequestedQueues;
222 0, // layerCount;
223 DE_NULL, // ppEnabledLayerNames;
224 0, // extensionCount;
225 DE_NULL, // ppEnabledExtensionNames;
226 DE_NULL, // pEnabledFeatures;
227 };
228
229 Move<VkDevice> resultingDevice = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instance, instanceDriver, physicalDevice, &deviceCreateInfo);
230
231 return tcu::TestStatus::pass("Pass");
232 }
233
234 } // anonymous
235
createFaultHandlingTests(tcu::TestContext & testCtx)236 tcu::TestCaseGroup* createFaultHandlingTests (tcu::TestContext& testCtx)
237 {
238 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "fault_handling", "Tests verifying Vulkan SC fault handling"));
239
240 // add tests for vkGetFaultData function
241 {
242 de::MovePtr<tcu::TestCaseGroup> getFaultDataGroup(new tcu::TestCaseGroup(testCtx, "get_fault_data", "Testing vkGetFaultData results"));
243
244 const struct
245 {
246 VkFaultQueryBehavior queryBehaviour;
247 const char* name;
248 } behaviours[] =
249 {
250 { VK_FAULT_QUERY_BEHAVIOR_GET_AND_CLEAR_ALL_FAULTS, "get_and_clear_all_faults" },
251 };
252
253 const struct
254 {
255 FHFaultValue faultValue;
256 const char* name;
257 } faults[] =
258 {
259 { FHF_NULL, "null" },
260 { FHF_ARRAY, "array" },
261 };
262
263 for (int behaviourIdx = 0; behaviourIdx < DE_LENGTH_OF_ARRAY(behaviours); ++behaviourIdx)
264 {
265 de::MovePtr<tcu::TestCaseGroup> behaviourGroup(new tcu::TestCaseGroup(testCtx, behaviours[behaviourIdx].name, ""));
266
267 for (int faultIdx = 0; faultIdx < DE_LENGTH_OF_ARRAY(faults); ++faultIdx)
268 {
269 TestParams testParams{ behaviours[behaviourIdx].queryBehaviour, faults[faultIdx].faultValue };
270
271 addFunctionCase(behaviourGroup.get(), faults[faultIdx].name, "", testGetFaultData, testParams);
272 }
273 getFaultDataGroup->addChild(behaviourGroup.release());
274 }
275 group->addChild(getFaultDataGroup.release());
276 }
277
278 // add tests for VkFaultCallbackInfo
279 {
280 de::MovePtr<tcu::TestCaseGroup> faultCallbackInfoGroup(new tcu::TestCaseGroup(testCtx, "fault_callback_info", "Testing vkGetFaultData results"));
281
282 {
283 FaultCallbackInfoTestParams testParams { true };
284 addFunctionCase(faultCallbackInfoGroup.get(), "create_device_with_callback_with_fault_data", "", testCreateDeviceWithFaultCallbackInfo, testParams);
285 }
286 {
287 FaultCallbackInfoTestParams testParams { false };
288 addFunctionCase(faultCallbackInfoGroup.get(), "create_device_with_callback_without_fault_data", "", testCreateDeviceWithFaultCallbackInfo, testParams);
289 }
290 group->addChild(faultCallbackInfoGroup.release());
291 }
292
293 return group.release();
294 }
295
296 } // sc
297
298 } // vkt
299