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