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 pipeline identifier tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktPipelineIdentifierTests.hpp"
25
26 #include <set>
27 #include <vector>
28 #include <string>
29
30 #include "vktTestCaseUtil.hpp"
31 #include "vkDefs.hpp"
32 #include "vkSafetyCriticalUtil.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "tcuTestLog.hpp"
36
37 namespace vkt
38 {
39 namespace sc
40 {
41
42 using namespace vk;
43
44 namespace
45 {
46
47 enum PIPipeline
48 {
49 PIP_UNUSED = 0,
50 PIP_GRAPHICS,
51 PIP_COMPUTE
52 };
53
54 enum PITTestType
55 {
56 PITT_UNUSED = 0,
57 PITT_MISSING_ID,
58 PITT_NONEXISTING_ID,
59 PITT_MATCHCONTROL
60 };
61
62 enum PITMatchControl
63 {
64 PIMC_UNUSED = 0,
65 PIMC_UUID_EXACT_MATCH
66 };
67
68 struct TestParams
69 {
70 PITTestType type;
71 PITMatchControl matchControl;
72 bool single;
73 };
74
createGraphicsShaders(SourceCollections & dst,TestParams testParams)75 void createGraphicsShaders(SourceCollections &dst, TestParams testParams)
76 {
77 uint32_t pipelineCount = testParams.single ? 1 : 3;
78
79 for (uint32_t i = 0; i < pipelineCount; ++i)
80 {
81 std::ostringstream name, code;
82 name << "vertex_" << i;
83 code << "#version 450\n"
84 "\n"
85 "void main (void)\n"
86 "{\n"
87 " gl_Position = vec4( "
88 << i
89 << ");\n"
90 "}\n";
91 dst.glslSources.add(name.str()) << glu::VertexSource(code.str());
92 }
93
94 for (uint32_t i = 0; i < pipelineCount; ++i)
95 {
96 std::ostringstream name, code;
97 name << "fragment_" << i;
98 code << "#version 450\n"
99 "\n"
100 "layout(location=0) out vec4 x;\n"
101 "void main (void)\n"
102 "{\n"
103 " x = vec4("
104 << i
105 << ");\n"
106 "}\n";
107 dst.glslSources.add(name.str()) << glu::FragmentSource(code.str());
108 }
109 }
110
createComputeShaders(SourceCollections & dst,TestParams testParams)111 void createComputeShaders(SourceCollections &dst, TestParams testParams)
112 {
113 uint32_t pipelineCount = testParams.single ? 1 : 3;
114
115 for (uint32_t i = 0; i < pipelineCount; ++i)
116 {
117 std::ostringstream name, code;
118 name << "compute_" << i;
119 code << "#version 450\n"
120 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
121 "void main (void)\n"
122 "{\n"
123 " uvec4 x = uvec4("
124 << i
125 << ");\n"
126 "}\n";
127
128 dst.glslSources.add(name.str()) << glu::ComputeSource(code.str());
129 }
130 }
131
testGraphicsPipelineIdentifier(Context & context,TestParams testParams)132 tcu::TestStatus testGraphicsPipelineIdentifier(Context &context, TestParams testParams)
133 {
134 const vk::PlatformInterface &vkp = context.getPlatformInterface();
135 const InstanceInterface &vki = context.getInstanceInterface();
136 const VkInstance instance = context.getInstance();
137 const DeviceInterface &vk = context.getDeviceInterface();
138 const VkDevice device = context.getDevice();
139 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
140
141 uint32_t pipelineCount = testParams.single ? 1 : 3;
142
143 std::vector<Move<VkShaderModule>> shaders;
144 for (uint32_t i = 0; i < pipelineCount; ++i)
145 {
146 {
147 std::ostringstream name;
148 name << "vertex_" << i;
149 shaders.emplace_back(createShaderModule(vk, device, context.getBinaryCollection().get(name.str()), 0));
150 }
151 {
152 std::ostringstream name;
153 name << "fragment_" << i;
154 shaders.emplace_back(createShaderModule(vk, device, context.getBinaryCollection().get(name.str()), 0));
155 }
156 }
157
158 std::vector<std::vector<VkPipelineShaderStageCreateInfo>> shaderStageCreateInfos(pipelineCount);
159 for (uint32_t i = 0; i < pipelineCount; ++i)
160 {
161 shaderStageCreateInfos[i].push_back({
162 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
163 DE_NULL, // const void* pNext;
164 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
165 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
166 *shaders[2 * i], // VkShaderModule shader;
167 "main", // const char* pName;
168 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
169 });
170 shaderStageCreateInfos[i].push_back({
171 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
172 DE_NULL, // const void* pNext;
173 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
174 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
175 *shaders[2 * i + 1], // VkShaderModule shader;
176 "main", // const char* pName;
177 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
178 });
179 }
180
181 std::vector<VkPipelineVertexInputStateCreateInfo> vertexInputStateCreateInfo(pipelineCount);
182 std::vector<VkPipelineInputAssemblyStateCreateInfo> inputAssemblyStateCreateInfo(pipelineCount);
183 std::vector<VkPipelineViewportStateCreateInfo> viewPortStateCreateInfo(pipelineCount);
184 std::vector<VkPipelineRasterizationStateCreateInfo> rasterizationStateCreateInfo(pipelineCount);
185 std::vector<VkPipelineMultisampleStateCreateInfo> multisampleStateCreateInfo(pipelineCount);
186 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentState(pipelineCount);
187 std::vector<VkPipelineColorBlendStateCreateInfo> colorBlendStateCreateInfo(pipelineCount);
188 std::vector<VkPipelineDynamicStateCreateInfo> dynamicStateCreateInfo(pipelineCount);
189 std::vector<std::vector<VkDynamicState>> dynamicStates{
190 {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR},
191 {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR},
192 {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR},
193 };
194
195 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
196 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
197 DE_NULL, // const void* pNext;
198 (VkPipelineLayoutCreateFlags)0u, // VkPipelineLayoutCreateFlags flags;
199 0u, // uint32_t setLayoutCount;
200 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
201 0u, // uint32_t pushConstantRangeCount;
202 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
203 };
204 Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
205
206 const VkFormat format = getRenderTargetFormat(vki, physicalDevice);
207
208 VkAttachmentDescription attachmentDescription;
209 VkAttachmentReference attachmentReference;
210 VkSubpassDescription subpassDescription;
211 VkRenderPassCreateInfo renderPassCreateInfo =
212 prepareSimpleRenderPassCI(format, attachmentDescription, attachmentReference, subpassDescription);
213 Move<VkRenderPass> renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
214
215 std::vector<VkGraphicsPipelineCreateInfo> graphicsPipelineCreateInfos(pipelineCount);
216 for (uint32_t i = 0; i < pipelineCount; ++i)
217 graphicsPipelineCreateInfos[i] = prepareSimpleGraphicsPipelineCI(
218 vertexInputStateCreateInfo[i], shaderStageCreateInfos[i], inputAssemblyStateCreateInfo[i],
219 viewPortStateCreateInfo[i], rasterizationStateCreateInfo[i], multisampleStateCreateInfo[i],
220 colorBlendAttachmentState[i], colorBlendStateCreateInfo[i], dynamicStateCreateInfo[i], dynamicStates[i],
221 *pipelineLayout, *renderPass);
222
223 std::vector<std::string> sourcePID{"IDG_0000", "IDG_1111", "IDG_2222"};
224 std::vector<std::string> destPID;
225
226 switch (testParams.type)
227 {
228 case PITT_MISSING_ID:
229 case PITT_NONEXISTING_ID:
230 destPID = {"IDG_XXXX", "IDG_1111", "IDG_2222"};
231 break;
232 case PITT_MATCHCONTROL:
233 switch (testParams.matchControl)
234 {
235 case PIMC_UUID_EXACT_MATCH:
236 destPID = {"IDG_0000", "IDG_1111", "IDG_2222"};
237 break;
238 default:
239 TCU_THROW(InternalError, "Unrecognized match control");
240 }
241 break;
242 default:
243 TCU_THROW(InternalError, "Unrecognized test type");
244 }
245
246 // fill pipeline identifiers with initial values, apply pipeline names from sourcePID
247 std::vector<VkPipelineOfflineCreateInfo> pipelineIDs;
248 for (uint32_t i = 0; i < pipelineCount; ++i)
249 {
250 pipelineIDs.emplace_back(resetPipelineOfflineCreateInfo());
251 applyPipelineIdentifier(pipelineIDs[i], sourcePID[i]);
252 }
253
254 switch (testParams.matchControl)
255 {
256 case PIMC_UUID_EXACT_MATCH:
257 for (uint32_t i = 0; i < pipelineCount; ++i)
258 pipelineIDs[i].matchControl = VK_PIPELINE_MATCH_CONTROL_APPLICATION_UUID_EXACT_MATCH;
259 break;
260 default:
261 TCU_THROW(InternalError, "Unrecognized match control");
262 }
263
264 if (!context.getTestContext().getCommandLine().isSubProcess())
265 {
266 // If it's a main process - we create graphics pipelines only to increase VkDeviceObjectReservationCreateInfo::computePipelineRequestCount.
267 // We also fill all pipeline identifiers with distinct values ( otherwise the framework will create pipeline identifiers itself )
268 for (uint32_t i = 0; i < pipelineCount; ++i)
269 {
270 pipelineIDs[i].pNext = graphicsPipelineCreateInfos[i].pNext;
271 graphicsPipelineCreateInfos[i].pNext = &pipelineIDs[i];
272 }
273
274 std::vector<Move<VkPipeline>> pipelines;
275 for (uint32_t i = 0; i < pipelineCount; ++i)
276 pipelines.emplace_back(createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfos[i]));
277 return tcu::TestStatus::pass("Pass");
278 }
279
280 for (uint32_t i = 0; i < pipelineCount; ++i)
281 context.getResourceInterface()->fillPoolEntrySize(pipelineIDs[i]);
282
283 // subprocess - we create the same pipeline, but we use vkCreateGraphicsPipelines directly to skip the framework
284 GetDeviceProcAddrFunc getDeviceProcAddrFunc =
285 (GetDeviceProcAddrFunc)vkp.getInstanceProcAddr(instance, "vkGetDeviceProcAddr");
286 CreateGraphicsPipelinesFunc createGraphicsPipelinesFunc =
287 (CreateGraphicsPipelinesFunc)getDeviceProcAddrFunc(device, "vkCreateGraphicsPipelines");
288 DestroyPipelineFunc destroyPipelineFunc = (DestroyPipelineFunc)getDeviceProcAddrFunc(device, "vkDestroyPipeline");
289 VkPipelineCache pipelineCache = context.getResourceInterface()->getPipelineCache(device);
290 std::vector<VkPipeline> pipelines(pipelineCount);
291
292 VkResult expectedResult;
293 std::vector<uint8_t> expectedNullHandle(pipelineCount);
294 switch (testParams.type)
295 {
296 case PITT_MISSING_ID:
297 expectedResult = VK_ERROR_NO_PIPELINE_MATCH;
298 expectedNullHandle[0] = 1;
299 for (uint32_t i = 1; i < pipelineCount; ++i)
300 {
301 // we are skipping pipeline identifier at index 0
302 applyPipelineIdentifier(pipelineIDs[i], destPID[i]);
303 pipelineIDs[i].pNext = graphicsPipelineCreateInfos[i].pNext;
304 graphicsPipelineCreateInfos[i].pNext = &pipelineIDs[i];
305 expectedNullHandle[i] = 0;
306 }
307 break;
308 case PITT_NONEXISTING_ID:
309 expectedResult = VK_ERROR_NO_PIPELINE_MATCH;
310 for (uint32_t i = 0; i < pipelineCount; ++i)
311 {
312 // Pipeline identifier at index 0 uses wrong ID for PITT_NONEXISTING_ID test
313 // or a proper one for PITT_MATCHCONTROL test
314 applyPipelineIdentifier(pipelineIDs[i], destPID[i]);
315 pipelineIDs[i].pNext = graphicsPipelineCreateInfos[i].pNext;
316 graphicsPipelineCreateInfos[i].pNext = &pipelineIDs[i];
317 expectedNullHandle[i] = (i == 0);
318 }
319 break;
320 case PITT_MATCHCONTROL:
321 expectedResult = VK_SUCCESS;
322 for (uint32_t i = 0; i < pipelineCount; ++i)
323 {
324 // Pipeline identifier at index 0 uses wrong ID for PITT_NONEXISTING_ID test
325 // or a proper one for PITT_MATCHCONTROL test
326 applyPipelineIdentifier(pipelineIDs[i], destPID[i]);
327 pipelineIDs[i].pNext = graphicsPipelineCreateInfos[i].pNext;
328 graphicsPipelineCreateInfos[i].pNext = &pipelineIDs[i];
329 expectedNullHandle[i] = 0;
330 }
331 break;
332 default:
333 TCU_THROW(InternalError, "Unrecognized match control");
334 }
335
336 VkResult result = createGraphicsPipelinesFunc(device, pipelineCache, pipelineCount,
337 graphicsPipelineCreateInfos.data(), DE_NULL, pipelines.data());
338 bool isOK = true;
339 for (uint32_t i = 0; i < pipelineCount; ++i)
340 {
341 if (expectedNullHandle[i] == 0 && pipelines[i] == DE_NULL)
342 {
343 context.getTestContext().getLog()
344 << tcu::TestLog::Message << "Pipeline " << i << " should be created" << tcu::TestLog::EndMessage;
345 isOK = false;
346 }
347 if (expectedNullHandle[i] != 0 && pipelines[i] != DE_NULL)
348 {
349 context.getTestContext().getLog()
350 << tcu::TestLog::Message << "Pipeline " << i << " should not be created" << tcu::TestLog::EndMessage;
351 isOK = false;
352 }
353 }
354
355 if (result != expectedResult)
356 {
357 context.getTestContext().getLog()
358 << tcu::TestLog::Message << "vkCreateGraphicsPipelines returned wrong VkResult" << tcu::TestLog::EndMessage;
359 isOK = false;
360 }
361
362 for (uint32_t i = 0; i < pipelineCount; ++i)
363 destroyPipelineFunc(device, pipelines[i], DE_NULL);
364
365 return isOK ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
366 }
367
testComputePipelineIdentifier(Context & context,TestParams testParams)368 tcu::TestStatus testComputePipelineIdentifier(Context &context, TestParams testParams)
369 {
370 const vk::PlatformInterface &vkp = context.getPlatformInterface();
371 const VkInstance instance = context.getInstance();
372 const DeviceInterface &vk = context.getDeviceInterface();
373 const VkDevice device = context.getDevice();
374
375 uint32_t pipelineCount = testParams.single ? 1 : 3;
376
377 std::vector<Move<VkShaderModule>> computeShaders;
378 for (uint32_t i = 0; i < pipelineCount; ++i)
379 {
380 std::ostringstream name;
381 name << "compute_" << i;
382 computeShaders.emplace_back(createShaderModule(vk, device, context.getBinaryCollection().get(name.str()), 0));
383 }
384
385 std::vector<VkPipelineShaderStageCreateInfo> shaderStageCreateInfos(pipelineCount);
386 for (uint32_t i = 0; i < pipelineCount; ++i)
387 {
388 shaderStageCreateInfos[i] = {
389 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
390 DE_NULL, // const void* pNext;
391 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
392 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
393 *computeShaders[i], // VkShaderModule shader;
394 "main", // const char* pName;
395 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
396 };
397 }
398
399 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
400 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
401 DE_NULL, // const void* pNext;
402 (VkPipelineLayoutCreateFlags)0u, // VkPipelineLayoutCreateFlags flags;
403 0u, // uint32_t setLayoutCount;
404 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
405 0u, // uint32_t pushConstantRangeCount;
406 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
407 };
408 Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
409
410 std::vector<VkComputePipelineCreateInfo> computePipelineCreateInfos(pipelineCount);
411 for (uint32_t i = 0; i < pipelineCount; ++i)
412 computePipelineCreateInfos[i] = prepareSimpleComputePipelineCI(shaderStageCreateInfos[i], *pipelineLayout);
413
414 std::vector<std::string> sourcePID{"IDC_0000", "IDC_1111", "IDC_2222"};
415 std::vector<std::string> destPID;
416
417 switch (testParams.type)
418 {
419 case PITT_MISSING_ID:
420 case PITT_NONEXISTING_ID:
421 destPID = {"IDC_XXXX", "IDC_1111", "IDC_2222"};
422 break;
423 case PITT_MATCHCONTROL:
424 switch (testParams.matchControl)
425 {
426 case PIMC_UUID_EXACT_MATCH:
427 destPID = {"IDC_0000", "IDC_1111", "IDC_2222"};
428 break;
429 default:
430 TCU_THROW(InternalError, "Unrecognized match control");
431 }
432 break;
433 default:
434 TCU_THROW(InternalError, "Unrecognized test type");
435 }
436
437 // fill pipeline identifiers with initial values, apply pipeline names from sourcePID
438 std::vector<VkPipelineOfflineCreateInfo> pipelineIDs;
439 for (uint32_t i = 0; i < pipelineCount; ++i)
440 {
441 pipelineIDs.emplace_back(resetPipelineOfflineCreateInfo());
442 applyPipelineIdentifier(pipelineIDs[i], sourcePID[i]);
443 }
444
445 switch (testParams.matchControl)
446 {
447 case PIMC_UUID_EXACT_MATCH:
448 for (uint32_t i = 0; i < pipelineCount; ++i)
449 pipelineIDs[i].matchControl = VK_PIPELINE_MATCH_CONTROL_APPLICATION_UUID_EXACT_MATCH;
450 break;
451 default:
452 TCU_THROW(InternalError, "Unrecognized match control");
453 }
454
455 if (!context.getTestContext().getCommandLine().isSubProcess())
456 {
457 // If it's a main process - we create compute pipelines only to increase VkDeviceObjectReservationCreateInfo::computePipelineRequestCount.
458 // We also fill all pipeline identifiers with distinct values ( otherwise the framework will create pipeline identifiers itself )
459 for (uint32_t i = 0; i < pipelineCount; ++i)
460 {
461 pipelineIDs[i].pNext = computePipelineCreateInfos[i].pNext;
462 computePipelineCreateInfos[i].pNext = &pipelineIDs[i];
463 }
464
465 std::vector<Move<VkPipeline>> pipelines;
466 for (uint32_t i = 0; i < pipelineCount; ++i)
467 pipelines.emplace_back(createComputePipeline(vk, device, DE_NULL, &computePipelineCreateInfos[i]));
468 return tcu::TestStatus::pass("Pass");
469 }
470
471 for (uint32_t i = 0; i < pipelineCount; ++i)
472 context.getResourceInterface()->fillPoolEntrySize(pipelineIDs[i]);
473
474 // In subprocess we create the same pipelines, but we use vkCreateGraphicsPipelines directly to skip the framework
475 GetDeviceProcAddrFunc getDeviceProcAddrFunc =
476 (GetDeviceProcAddrFunc)vkp.getInstanceProcAddr(instance, "vkGetDeviceProcAddr");
477 CreateComputePipelinesFunc createComputePipelinesFunc =
478 (CreateComputePipelinesFunc)getDeviceProcAddrFunc(device, "vkCreateComputePipelines");
479 DestroyPipelineFunc destroyPipelineFunc = (DestroyPipelineFunc)getDeviceProcAddrFunc(device, "vkDestroyPipeline");
480 VkPipelineCache pipelineCache = context.getResourceInterface()->getPipelineCache(device);
481 std::vector<VkPipeline> pipelines(pipelineCount);
482
483 VkResult expectedResult;
484 std::vector<uint8_t> expectedNullHandle(pipelineCount);
485 switch (testParams.type)
486 {
487 case PITT_MISSING_ID:
488 expectedResult = VK_ERROR_NO_PIPELINE_MATCH;
489 expectedNullHandle[0] = 1;
490 for (uint32_t i = 1; i < pipelineCount; ++i)
491 {
492 // we are skipping pipeline identifier at index 0
493 applyPipelineIdentifier(pipelineIDs[i], destPID[i]);
494 pipelineIDs[i].pNext = computePipelineCreateInfos[i].pNext;
495 computePipelineCreateInfos[i].pNext = &pipelineIDs[i];
496 expectedNullHandle[i] = 0;
497 }
498 break;
499 case PITT_NONEXISTING_ID:
500 expectedResult = VK_ERROR_NO_PIPELINE_MATCH;
501 for (uint32_t i = 0; i < pipelineCount; ++i)
502 {
503 // Pipeline identifier at index 0 uses wrong ID for PITT_NONEXISTING_ID test
504 // or a proper one for PITT_MATCHCONTROL test
505 applyPipelineIdentifier(pipelineIDs[i], destPID[i]);
506 pipelineIDs[i].pNext = computePipelineCreateInfos[i].pNext;
507 computePipelineCreateInfos[i].pNext = &pipelineIDs[i];
508 expectedNullHandle[i] = (i == 0);
509 }
510 break;
511 case PITT_MATCHCONTROL:
512 expectedResult = VK_SUCCESS;
513 for (uint32_t i = 0; i < pipelineCount; ++i)
514 {
515 // Pipeline identifier at index 0 uses wrong ID for PITT_NONEXISTING_ID test
516 // or a proper one for PITT_MATCHCONTROL test
517 applyPipelineIdentifier(pipelineIDs[i], destPID[i]);
518 pipelineIDs[i].pNext = computePipelineCreateInfos[i].pNext;
519 computePipelineCreateInfos[i].pNext = &pipelineIDs[i];
520 expectedNullHandle[i] = 0;
521 }
522 break;
523 default:
524 TCU_THROW(InternalError, "Unrecognized match control");
525 }
526
527 VkResult result = createComputePipelinesFunc(device, pipelineCache, pipelineCount,
528 computePipelineCreateInfos.data(), DE_NULL, pipelines.data());
529
530 bool isOK = true;
531 for (uint32_t i = 0; i < pipelineCount; ++i)
532 {
533 if (expectedNullHandle[i] == 0 && pipelines[i] == DE_NULL)
534 {
535 context.getTestContext().getLog()
536 << tcu::TestLog::Message << "Pipeline " << i << " should be created" << tcu::TestLog::EndMessage;
537 isOK = false;
538 }
539 if (expectedNullHandle[i] != 0 && pipelines[i] != DE_NULL)
540 {
541 context.getTestContext().getLog()
542 << tcu::TestLog::Message << "Pipeline " << i << " should not be created" << tcu::TestLog::EndMessage;
543 isOK = false;
544 }
545 }
546
547 if (result != expectedResult)
548 {
549 context.getTestContext().getLog()
550 << tcu::TestLog::Message << "vkCreateComputePipelines returned wrong VkResult" << tcu::TestLog::EndMessage;
551 isOK = false;
552 }
553
554 for (uint32_t i = 0; i < pipelineCount; ++i)
555 destroyPipelineFunc(device, pipelines[i], DE_NULL);
556
557 return isOK ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
558 }
559
560 } // namespace
561
createPipelineIdentifierTests(tcu::TestContext & testCtx)562 tcu::TestCaseGroup *createPipelineIdentifierTests(tcu::TestContext &testCtx)
563 {
564 // Tests verifying Vulkan SC pipeline identifier structure
565 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "pipeline_identifier"));
566
567 const struct
568 {
569 PIPipeline pipeline;
570 const char *name;
571 FunctionPrograms1<TestParams>::Function initPrograms;
572 FunctionInstance1<TestParams>::Function testFunction;
573 } pipelineTypes[] = {
574 {PIP_GRAPHICS, "graphics", createGraphicsShaders, testGraphicsPipelineIdentifier},
575 {PIP_COMPUTE, "compute", createComputeShaders, testComputePipelineIdentifier},
576 };
577
578 const struct
579 {
580 PITTestType type;
581 const char *name;
582 } testTypes[] = {
583 {PITT_MISSING_ID, "missing_pid"},
584 {PITT_NONEXISTING_ID, "nonexisting_pid"},
585 {PITT_MATCHCONTROL, "match_control"},
586 };
587
588 const struct
589 {
590 PITMatchControl control;
591 const char *name;
592 } matchControls[] = {
593 {PIMC_UUID_EXACT_MATCH, "exact_match"},
594 };
595
596 const struct
597 {
598 bool single;
599 const char *name;
600 } cardinalities[] = {
601 {true, "single"},
602 {false, "multiple"},
603 };
604
605 for (int pipelineIdx = 0; pipelineIdx < DE_LENGTH_OF_ARRAY(pipelineTypes); ++pipelineIdx)
606 {
607 de::MovePtr<tcu::TestCaseGroup> pipelineGroup(new tcu::TestCaseGroup(testCtx, pipelineTypes[pipelineIdx].name));
608
609 for (int typeIdx = 0; typeIdx < DE_LENGTH_OF_ARRAY(testTypes); ++typeIdx)
610 {
611 de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(testCtx, testTypes[typeIdx].name));
612
613 for (int matchIdx = 0; matchIdx < DE_LENGTH_OF_ARRAY(matchControls); ++matchIdx)
614 {
615 de::MovePtr<tcu::TestCaseGroup> matchGroup(
616 new tcu::TestCaseGroup(testCtx, matchControls[matchIdx].name));
617
618 for (int cardIdx = 0; cardIdx < DE_LENGTH_OF_ARRAY(cardinalities); ++cardIdx)
619 {
620 TestParams testParams{testTypes[typeIdx].type, matchControls[matchIdx].control,
621 cardinalities[cardIdx].single};
622
623 addFunctionCaseWithPrograms(matchGroup.get(), cardinalities[cardIdx].name,
624 pipelineTypes[pipelineIdx].initPrograms,
625 pipelineTypes[pipelineIdx].testFunction, testParams);
626 }
627 typeGroup->addChild(matchGroup.release());
628 }
629 pipelineGroup->addChild(typeGroup.release());
630 }
631 group->addChild(pipelineGroup.release());
632 }
633 return group.release();
634 }
635
636 } // namespace sc
637
638 } // namespace vkt
639