1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 Google 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 Utility for pre-compiling source programs to SPIR-V
22 *//*--------------------------------------------------------------------*/
23
24 #include "tcuDefs.hpp"
25 #include "tcuCommandLine.hpp"
26 #include "tcuPlatform.hpp"
27 #include "tcuResource.hpp"
28 #include "tcuTestLog.hpp"
29 #include "tcuTestHierarchyIterator.hpp"
30 #include "deUniquePtr.hpp"
31 #include "vkPrograms.hpp"
32 #include "vkBinaryRegistry.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktTestPackage.hpp"
35 #include "deUniquePtr.hpp"
36 #include "deCommandLine.hpp"
37 #include "deSharedPtr.hpp"
38 #include "deThread.hpp"
39 #include "deThreadSafeRingBuffer.hpp"
40 #include "dePoolArray.hpp"
41
42 #include <iostream>
43
44 using std::vector;
45 using std::string;
46 using de::UniquePtr;
47 using de::MovePtr;
48 using de::SharedPtr;
49
50 namespace vkt
51 {
52
53 namespace // anonymous
54 {
55
56 typedef de::SharedPtr<glu::ProgramSources> ProgramSourcesSp;
57 typedef de::SharedPtr<vk::SpirVAsmSource> SpirVAsmSourceSp;
58 typedef de::SharedPtr<vk::ProgramBinary> ProgramBinarySp;
59
60 class Task
61 {
62 public:
63 virtual void execute (void) = 0;
64 };
65
66 typedef de::ThreadSafeRingBuffer<Task*> TaskQueue;
67
68 class TaskExecutorThread : public de::Thread
69 {
70 public:
TaskExecutorThread(TaskQueue & tasks)71 TaskExecutorThread (TaskQueue& tasks)
72 : m_tasks(tasks)
73 {
74 start();
75 }
76
run(void)77 void run (void)
78 {
79 for (;;)
80 {
81 Task* const task = m_tasks.popBack();
82
83 if (task)
84 task->execute();
85 else
86 break; // End of tasks - time to terminate
87 }
88 }
89
90 private:
91 TaskQueue& m_tasks;
92 };
93
94 class TaskExecutor
95 {
96 public:
97 TaskExecutor (deUint32 numThreads);
98 ~TaskExecutor (void);
99
100 void submit (Task* task);
101 void waitForComplete (void);
102
103 private:
104 typedef de::SharedPtr<TaskExecutorThread> ExecThreadSp;
105
106 std::vector<ExecThreadSp> m_threads;
107 TaskQueue m_tasks;
108 };
109
TaskExecutor(deUint32 numThreads)110 TaskExecutor::TaskExecutor (deUint32 numThreads)
111 : m_threads (numThreads)
112 , m_tasks (m_threads.size() * 1024u)
113 {
114 for (size_t ndx = 0; ndx < m_threads.size(); ++ndx)
115 m_threads[ndx] = ExecThreadSp(new TaskExecutorThread(m_tasks));
116 }
117
~TaskExecutor(void)118 TaskExecutor::~TaskExecutor (void)
119 {
120 for (size_t ndx = 0; ndx < m_threads.size(); ++ndx)
121 m_tasks.pushFront(DE_NULL);
122
123 for (size_t ndx = 0; ndx < m_threads.size(); ++ndx)
124 m_threads[ndx]->join();
125 }
126
submit(Task * task)127 void TaskExecutor::submit (Task* task)
128 {
129 DE_ASSERT(task);
130 m_tasks.pushFront(task);
131 }
132
133 class SyncTask : public Task
134 {
135 public:
SyncTask(de::Semaphore * enterBarrier,de::Semaphore * inBarrier,de::Semaphore * leaveBarrier)136 SyncTask (de::Semaphore* enterBarrier, de::Semaphore* inBarrier, de::Semaphore* leaveBarrier)
137 : m_enterBarrier (enterBarrier)
138 , m_inBarrier (inBarrier)
139 , m_leaveBarrier (leaveBarrier)
140 {}
141
SyncTask(void)142 SyncTask (void)
143 : m_enterBarrier (DE_NULL)
144 , m_inBarrier (DE_NULL)
145 , m_leaveBarrier (DE_NULL)
146 {}
147
execute(void)148 void execute (void)
149 {
150 m_enterBarrier->increment();
151 m_inBarrier->decrement();
152 m_leaveBarrier->increment();
153 }
154
155 private:
156 de::Semaphore* m_enterBarrier;
157 de::Semaphore* m_inBarrier;
158 de::Semaphore* m_leaveBarrier;
159 };
160
waitForComplete(void)161 void TaskExecutor::waitForComplete (void)
162 {
163 de::Semaphore enterBarrier (0);
164 de::Semaphore inBarrier (0);
165 de::Semaphore leaveBarrier (0);
166 std::vector<SyncTask> syncTasks (m_threads.size());
167
168 for (size_t ndx = 0; ndx < m_threads.size(); ++ndx)
169 {
170 syncTasks[ndx] = SyncTask(&enterBarrier, &inBarrier, &leaveBarrier);
171 submit(&syncTasks[ndx]);
172 }
173
174 for (size_t ndx = 0; ndx < m_threads.size(); ++ndx)
175 enterBarrier.decrement();
176
177 for (size_t ndx = 0; ndx < m_threads.size(); ++ndx)
178 inBarrier.increment();
179
180 for (size_t ndx = 0; ndx < m_threads.size(); ++ndx)
181 leaveBarrier.decrement();
182 }
183
184 struct Program
185 {
186 enum Status
187 {
188 STATUS_NOT_COMPLETED = 0,
189 STATUS_FAILED,
190 STATUS_PASSED,
191
192 STATUS_LAST
193 };
194
195 vk::ProgramIdentifier id;
196
197 Status buildStatus;
198 std::string buildLog;
199 ProgramBinarySp binary;
200
201 Status validationStatus;
202 std::string validationLog;
203
204 vk::SpirvValidatorOptions validatorOptions;
205
Programvkt::__anon5c239db60111::Program206 explicit Program (const vk::ProgramIdentifier& id_, const vk::SpirvValidatorOptions& valOptions_)
207 : id (id_)
208 , buildStatus (STATUS_NOT_COMPLETED)
209 , validationStatus (STATUS_NOT_COMPLETED)
210 , validatorOptions (valOptions_)
211 {}
Programvkt::__anon5c239db60111::Program212 Program (void)
213 : id ("", "")
214 , buildStatus (STATUS_NOT_COMPLETED)
215 , validationStatus (STATUS_NOT_COMPLETED)
216 , validatorOptions()
217 {}
218 };
219
writeBuildLogs(const glu::ShaderProgramInfo & buildInfo,std::ostream & dst)220 void writeBuildLogs (const glu::ShaderProgramInfo& buildInfo, std::ostream& dst)
221 {
222 for (size_t shaderNdx = 0; shaderNdx < buildInfo.shaders.size(); shaderNdx++)
223 {
224 const glu::ShaderInfo& shaderInfo = buildInfo.shaders[shaderNdx];
225 const char* const shaderName = getShaderTypeName(shaderInfo.type);
226
227 dst << shaderName << " source:\n"
228 << "---\n"
229 << shaderInfo.source << "\n"
230 << "---\n"
231 << shaderName << " compile log:\n"
232 << "---\n"
233 << shaderInfo.infoLog << "\n"
234 << "---\n";
235 }
236
237 dst << "link log:\n"
238 << "---\n"
239 << buildInfo.program.infoLog << "\n"
240 << "---\n";
241 }
242
243 template <typename Source>
244 class BuildHighLevelShaderTask : public Task
245 {
246 public:
247
BuildHighLevelShaderTask(const Source & source,Program * program)248 BuildHighLevelShaderTask (const Source& source, Program* program)
249 : m_source (source)
250 , m_program (program)
251 , m_commandLine (0)
252 {}
253
BuildHighLevelShaderTask(void)254 BuildHighLevelShaderTask (void) : m_program(DE_NULL) {}
255
setCommandline(const tcu::CommandLine & commandLine)256 void setCommandline (const tcu::CommandLine &commandLine)
257 {
258 m_commandLine = &commandLine;
259 }
260
execute(void)261 void execute (void)
262 {
263 glu::ShaderProgramInfo buildInfo;
264
265 try
266 {
267 DE_ASSERT(m_source.buildOptions.targetVersion < vk::SPIRV_VERSION_LAST);
268 DE_ASSERT(m_commandLine != DE_NULL);
269 m_program->binary = ProgramBinarySp(vk::buildProgram(m_source, &buildInfo, *m_commandLine));
270 m_program->buildStatus = Program::STATUS_PASSED;
271 m_program->validatorOptions = m_source.buildOptions.getSpirvValidatorOptions();
272 }
273 catch (const tcu::Exception&)
274 {
275 std::ostringstream log;
276
277 writeBuildLogs(buildInfo, log);
278
279 m_program->buildStatus = Program::STATUS_FAILED;
280 m_program->buildLog = log.str();
281 }
282 }
283
284 private:
285 Source m_source;
286 Program* m_program;
287 const tcu::CommandLine* m_commandLine;
288 };
289
writeBuildLogs(const vk::SpirVProgramInfo & buildInfo,std::ostream & dst)290 void writeBuildLogs (const vk::SpirVProgramInfo& buildInfo, std::ostream& dst)
291 {
292 dst << "source:\n"
293 << "---\n"
294 << buildInfo.source << "\n"
295 << "---\n"
296 << buildInfo.infoLog << "\n"
297 << "---\n";
298 }
299
300 class BuildSpirVAsmTask : public Task
301 {
302 public:
BuildSpirVAsmTask(const vk::SpirVAsmSource & source,Program * program)303 BuildSpirVAsmTask (const vk::SpirVAsmSource& source, Program* program)
304 : m_source (source)
305 , m_program (program)
306 , m_commandLine (0)
307 {}
308
BuildSpirVAsmTask(void)309 BuildSpirVAsmTask (void) : m_program(DE_NULL) {}
310
setCommandline(const tcu::CommandLine & commandLine)311 void setCommandline (const tcu::CommandLine &commandLine)
312 {
313 m_commandLine = &commandLine;
314 }
315
execute(void)316 void execute (void)
317 {
318 vk::SpirVProgramInfo buildInfo;
319
320 try
321 {
322 DE_ASSERT(m_source.buildOptions.targetVersion < vk::SPIRV_VERSION_LAST);
323 DE_ASSERT(m_commandLine != DE_NULL);
324 m_program->binary = ProgramBinarySp(vk::assembleProgram(m_source, &buildInfo, *m_commandLine));
325 m_program->buildStatus = Program::STATUS_PASSED;
326 }
327 catch (const tcu::Exception&)
328 {
329 std::ostringstream log;
330
331 writeBuildLogs(buildInfo, log);
332
333 m_program->buildStatus = Program::STATUS_FAILED;
334 m_program->buildLog = log.str();
335 }
336 }
337
338 private:
339 vk::SpirVAsmSource m_source;
340 Program* m_program;
341 const tcu::CommandLine* m_commandLine;
342 };
343
344 class ValidateBinaryTask : public Task
345 {
346 public:
ValidateBinaryTask(Program * program)347 ValidateBinaryTask (Program* program)
348 : m_program(program)
349 {}
350
execute(void)351 void execute (void)
352 {
353 DE_ASSERT(m_program->buildStatus == Program::STATUS_PASSED);
354 DE_ASSERT(m_program->binary->getFormat() == vk::PROGRAM_FORMAT_SPIRV);
355
356 std::ostringstream validationLogStream;
357
358 if (vk::validateProgram(*m_program->binary, &validationLogStream, m_program->validatorOptions))
359 m_program->validationStatus = Program::STATUS_PASSED;
360 else
361 m_program->validationStatus = Program::STATUS_FAILED;
362 m_program->validationLog = validationLogStream.str();
363 }
364
365 private:
366 Program* m_program;
367 };
368
createRoot(tcu::TestContext & testCtx)369 tcu::TestPackageRoot* createRoot (tcu::TestContext& testCtx)
370 {
371 vector<tcu::TestNode*> children;
372 children.push_back(new TestPackage(testCtx));
373 return new tcu::TestPackageRoot(testCtx, children);
374 }
375
376 } // anonymous
377
378 struct BuildStats
379 {
380 int numSucceeded;
381 int numFailed;
382 int notSupported;
383
BuildStatsvkt::BuildStats384 BuildStats (void)
385 : numSucceeded (0)
386 , numFailed (0)
387 , notSupported (0)
388 {
389 }
390 };
391
buildPrograms(tcu::TestContext & testCtx,const std::string & dstPath,const bool validateBinaries,const deUint32 usedVulkanVersion,const vk::SpirvVersion baselineSpirvVersion,const vk::SpirvVersion maxSpirvVersion,const bool allowSpirV14)392 BuildStats buildPrograms (tcu::TestContext& testCtx,
393 const std::string& dstPath,
394 const bool validateBinaries,
395 const deUint32 usedVulkanVersion,
396 const vk::SpirvVersion baselineSpirvVersion,
397 const vk::SpirvVersion maxSpirvVersion,
398 const bool allowSpirV14)
399 {
400 const deUint32 numThreads = deGetNumAvailableLogicalCores();
401
402 TaskExecutor executor (numThreads);
403
404 // de::PoolArray<> is faster to build than std::vector
405 de::MemPool programPool;
406 de::PoolArray<Program> programs (&programPool);
407 int notSupported = 0;
408
409 {
410 de::MemPool tmpPool;
411 de::PoolArray<BuildHighLevelShaderTask<vk::GlslSource> > buildGlslTasks (&tmpPool);
412 de::PoolArray<BuildHighLevelShaderTask<vk::HlslSource> > buildHlslTasks (&tmpPool);
413 de::PoolArray<BuildSpirVAsmTask> buildSpirvAsmTasks (&tmpPool);
414
415 // Collect build tasks
416 {
417 const UniquePtr<tcu::TestPackageRoot> root (createRoot(testCtx));
418 tcu::DefaultHierarchyInflater inflater (testCtx);
419 de::MovePtr<tcu::CaseListFilter> caseListFilter (testCtx.getCommandLine().createCaseListFilter(testCtx.getArchive()));
420 tcu::TestHierarchyIterator iterator (*root, inflater, *caseListFilter);
421
422 while (iterator.getState() != tcu::TestHierarchyIterator::STATE_FINISHED)
423 {
424 if (iterator.getState() == tcu::TestHierarchyIterator::STATE_ENTER_NODE &&
425 tcu::isTestNodeTypeExecutable(iterator.getNode()->getNodeType()))
426 {
427 TestCase* const testCase = dynamic_cast<TestCase*>(iterator.getNode());
428 const string casePath = iterator.getNodePath();
429 vk::ShaderBuildOptions defaultGlslBuildOptions (usedVulkanVersion, baselineSpirvVersion, 0u);
430 vk::ShaderBuildOptions defaultHlslBuildOptions (usedVulkanVersion, baselineSpirvVersion, 0u);
431 vk::SpirVAsmBuildOptions defaultSpirvAsmBuildOptions (usedVulkanVersion, baselineSpirvVersion);
432 vk::SourceCollections sourcePrograms (usedVulkanVersion, defaultGlslBuildOptions, defaultHlslBuildOptions, defaultSpirvAsmBuildOptions);
433
434 try
435 {
436 testCase->delayedInit();
437 testCase->initPrograms(sourcePrograms);
438 }
439 catch (const tcu::NotSupportedError& )
440 {
441 notSupported++;
442 iterator.next();
443 continue;
444 }
445
446 for (vk::GlslSourceCollection::Iterator progIter = sourcePrograms.glslSources.begin();
447 progIter != sourcePrograms.glslSources.end();
448 ++progIter)
449 {
450 // Source program requires higher SPIR-V version than available: skip it to avoid fail
451 // Unless this is SPIR-V 1.4 and is explicitly allowed.
452 if (progIter.getProgram().buildOptions.targetVersion > maxSpirvVersion && !(allowSpirV14 && progIter.getProgram().buildOptions.supports_VK_KHR_spirv_1_4 && progIter.getProgram().buildOptions.targetVersion == vk::SPIRV_VERSION_1_4))
453 continue;
454
455 programs.pushBack(Program(vk::ProgramIdentifier(casePath, progIter.getName()), progIter.getProgram().buildOptions.getSpirvValidatorOptions()));
456 buildGlslTasks.pushBack(BuildHighLevelShaderTask<vk::GlslSource>(progIter.getProgram(), &programs.back()));
457 buildGlslTasks.back().setCommandline(testCtx.getCommandLine());
458 executor.submit(&buildGlslTasks.back());
459 }
460
461 for (vk::HlslSourceCollection::Iterator progIter = sourcePrograms.hlslSources.begin();
462 progIter != sourcePrograms.hlslSources.end();
463 ++progIter)
464 {
465 // Source program requires higher SPIR-V version than available: skip it to avoid fail
466 // Unless this is SPIR-V 1.4 and is explicitly allowed.
467 if (progIter.getProgram().buildOptions.targetVersion > maxSpirvVersion && !(allowSpirV14 && progIter.getProgram().buildOptions.supports_VK_KHR_spirv_1_4 && progIter.getProgram().buildOptions.targetVersion == vk::SPIRV_VERSION_1_4))
468 continue;
469
470 programs.pushBack(Program(vk::ProgramIdentifier(casePath, progIter.getName()), progIter.getProgram().buildOptions.getSpirvValidatorOptions()));
471 buildHlslTasks.pushBack(BuildHighLevelShaderTask<vk::HlslSource>(progIter.getProgram(), &programs.back()));
472 buildHlslTasks.back().setCommandline(testCtx.getCommandLine());
473 executor.submit(&buildHlslTasks.back());
474 }
475
476 for (vk::SpirVAsmCollection::Iterator progIter = sourcePrograms.spirvAsmSources.begin();
477 progIter != sourcePrograms.spirvAsmSources.end();
478 ++progIter)
479 {
480 // Source program requires higher SPIR-V version than available: skip it to avoid fail
481 // Unless this is SPIR-V 1.4 and is explicitly allowed.
482 if (progIter.getProgram().buildOptions.targetVersion > maxSpirvVersion && !(allowSpirV14 && progIter.getProgram().buildOptions.supports_VK_KHR_spirv_1_4 && progIter.getProgram().buildOptions.targetVersion == vk::SPIRV_VERSION_1_4))
483 continue;
484
485 programs.pushBack(Program(vk::ProgramIdentifier(casePath, progIter.getName()), progIter.getProgram().buildOptions.getSpirvValidatorOptions()));
486 buildSpirvAsmTasks.pushBack(BuildSpirVAsmTask(progIter.getProgram(), &programs.back()));
487 buildSpirvAsmTasks.back().setCommandline(testCtx.getCommandLine());
488 executor.submit(&buildSpirvAsmTasks.back());
489 }
490 }
491
492 iterator.next();
493 }
494 }
495
496 // Need to wait until tasks completed before freeing task memory
497 executor.waitForComplete();
498 }
499
500 if (validateBinaries)
501 {
502 std::vector<ValidateBinaryTask> validationTasks;
503
504 validationTasks.reserve(programs.size());
505
506 for (de::PoolArray<Program>::iterator progIter = programs.begin(); progIter != programs.end(); ++progIter)
507 {
508 if (progIter->buildStatus == Program::STATUS_PASSED)
509 {
510 validationTasks.push_back(ValidateBinaryTask(&*progIter));
511 executor.submit(&validationTasks.back());
512 }
513 }
514
515 executor.waitForComplete();
516 }
517
518 {
519 vk::BinaryRegistryWriter registryWriter (dstPath);
520
521 for (de::PoolArray<Program>::iterator progIter = programs.begin(); progIter != programs.end(); ++progIter)
522 {
523 if (progIter->buildStatus == Program::STATUS_PASSED)
524 registryWriter.addProgram(progIter->id, *progIter->binary);
525 }
526
527 registryWriter.write();
528 }
529
530 {
531 BuildStats stats;
532 stats.notSupported = notSupported;
533 for (de::PoolArray<Program>::iterator progIter = programs.begin(); progIter != programs.end(); ++progIter)
534 {
535 const bool buildOk = progIter->buildStatus == Program::STATUS_PASSED;
536 const bool validationOk = progIter->validationStatus != Program::STATUS_FAILED;
537
538 if (buildOk && validationOk)
539 stats.numSucceeded += 1;
540 else
541 {
542 stats.numFailed += 1;
543 tcu::print("ERROR: %s / %s: %s failed\n",
544 progIter->id.testCasePath.c_str(),
545 progIter->id.programName.c_str(),
546 (buildOk ? "validation" : "build"));
547 tcu::print("%s\n", (buildOk ? progIter->validationLog.c_str() : progIter->buildLog.c_str()));
548 }
549 }
550
551 return stats;
552 }
553 }
554
555 } // vkt
556
557 namespace opt
558 {
559
560 DE_DECLARE_COMMAND_LINE_OPT(DstPath, std::string);
561 DE_DECLARE_COMMAND_LINE_OPT(Cases, std::string);
562 DE_DECLARE_COMMAND_LINE_OPT(Validate, bool);
563 DE_DECLARE_COMMAND_LINE_OPT(VulkanVersion, deUint32);
564 DE_DECLARE_COMMAND_LINE_OPT(ShaderCache, bool);
565 DE_DECLARE_COMMAND_LINE_OPT(ShaderCacheFilename, std::string);
566 DE_DECLARE_COMMAND_LINE_OPT(ShaderCacheTruncate, bool);
567 DE_DECLARE_COMMAND_LINE_OPT(SpirvOptimize, bool);
568 DE_DECLARE_COMMAND_LINE_OPT(SpirvOptimizationRecipe,std::string);
569 DE_DECLARE_COMMAND_LINE_OPT(SpirvAllow14, bool);
570
571 static const de::cmdline::NamedValue<bool> s_enableNames[] =
572 {
573 { "enable", true },
574 { "disable", false }
575 };
576
registerOptions(de::cmdline::Parser & parser)577 void registerOptions (de::cmdline::Parser& parser)
578 {
579 using de::cmdline::Option;
580 using de::cmdline::NamedValue;
581
582 static const NamedValue<deUint32> s_vulkanVersion[] =
583 {
584 { "1.0", VK_MAKE_VERSION(1, 0, 0) },
585 { "1.1", VK_MAKE_VERSION(1, 1, 0) },
586 { "1.2", VK_MAKE_VERSION(1, 2, 0) },
587 };
588
589 DE_STATIC_ASSERT(vk::SPIRV_VERSION_1_5 + 1 == vk::SPIRV_VERSION_LAST);
590
591 parser << Option<opt::DstPath>("d", "dst-path", "Destination path", "out")
592 << Option<opt::Cases>("n", "deqp-case", "Case path filter (works as in test binaries)")
593 << Option<opt::Validate>("v", "validate-spv", "Validate generated SPIR-V binaries")
594 << Option<opt::VulkanVersion>("t", "target-vulkan-version", "Target Vulkan version", s_vulkanVersion, "1.2")
595 << Option<opt::ShaderCache>("s", "shadercache", "Enable or disable shader cache", s_enableNames, "enable")
596 << Option<opt::ShaderCacheFilename>("r", "shadercache-filename", "Write shader cache to given file", "shadercache.bin")
597 << Option<opt::ShaderCacheTruncate>("x", "shadercache-truncate", "Truncate shader cache before running", s_enableNames, "enable")
598 << Option<opt::SpirvOptimize>("o", "deqp-optimize-spirv", "Enable optimization for SPIR-V", s_enableNames, "disable")
599 << Option<opt::SpirvOptimizationRecipe>("p","deqp-optimization-recipe", "Shader optimization recipe")
600 << Option<opt::SpirvAllow14>("e","allow-spirv-14", "Allow SPIR-V 1.4 with Vulkan 1.1");
601 }
602
603 } // opt
604
main(int argc,const char * argv[])605 int main (int argc, const char* argv[])
606 {
607 de::cmdline::CommandLine cmdLine;
608 tcu::CommandLine deqpCmdLine;
609
610 {
611 de::cmdline::Parser parser;
612 opt::registerOptions(parser);
613 if (!parser.parse(argc, argv, &cmdLine, std::cerr))
614 {
615 parser.help(std::cout);
616 return -1;
617 }
618 }
619
620 {
621 vector<const char*> deqpArgv;
622
623 deqpArgv.push_back("unused");
624
625 if (cmdLine.hasOption<opt::Cases>())
626 {
627 deqpArgv.push_back("--deqp-case");
628 deqpArgv.push_back(cmdLine.getOption<opt::Cases>().c_str());
629 }
630
631 if (cmdLine.hasOption<opt::ShaderCacheFilename>())
632 {
633 deqpArgv.push_back("--deqp-shadercache-filename");
634 deqpArgv.push_back(cmdLine.getOption<opt::ShaderCacheFilename>().c_str());
635 }
636
637 if (cmdLine.hasOption<opt::ShaderCache>())
638 {
639 deqpArgv.push_back("--deqp-shadercache");
640 if (cmdLine.getOption<opt::ShaderCache>())
641 deqpArgv.push_back("enable");
642 else
643 deqpArgv.push_back("disable");
644 }
645
646 if (cmdLine.hasOption<opt::ShaderCacheTruncate>())
647 {
648 deqpArgv.push_back("--deqp-shadercache-truncate");
649 if (cmdLine.getOption<opt::ShaderCacheTruncate>())
650 deqpArgv.push_back("enable");
651 else
652 deqpArgv.push_back("disable");
653 }
654
655 if (cmdLine.hasOption<opt::SpirvOptimize>())
656 {
657 deqpArgv.push_back("--deqp-optimize-spirv");
658 if (cmdLine.getOption<opt::SpirvOptimize>())
659 deqpArgv.push_back("enable");
660 else
661 deqpArgv.push_back("disable");
662 }
663
664 if (cmdLine.hasOption<opt::SpirvOptimizationRecipe>())
665 {
666 deqpArgv.push_back("--deqp-optimization-recipe");
667 deqpArgv.push_back(cmdLine.getOption<opt::SpirvOptimizationRecipe>().c_str());
668 }
669
670 if (!deqpCmdLine.parse((int)deqpArgv.size(), &deqpArgv[0]))
671 return -1;
672 }
673
674 try
675 {
676 tcu::DirArchive archive (".");
677 tcu::TestLog log (deqpCmdLine.getLogFileName(), deqpCmdLine.getLogFlags());
678 tcu::Platform platform;
679 tcu::TestContext testCtx (platform, archive, log, deqpCmdLine, DE_NULL);
680 vk::SpirvVersion baselineSpirvVersion = vk::getBaselineSpirvVersion(cmdLine.getOption<opt::VulkanVersion>());
681 vk::SpirvVersion maxSpirvVersion = vk::getMaxSpirvVersionForGlsl(cmdLine.getOption<opt::VulkanVersion>());
682
683 testCtx.writeSessionInfo();
684
685 tcu::print("SPIR-V versions: baseline: %s, max supported: %s\n",
686 getSpirvVersionName(baselineSpirvVersion).c_str(),
687 getSpirvVersionName(maxSpirvVersion).c_str());
688
689 const vkt::BuildStats stats = vkt::buildPrograms(testCtx,
690 cmdLine.getOption<opt::DstPath>(),
691 cmdLine.getOption<opt::Validate>(),
692 cmdLine.getOption<opt::VulkanVersion>(),
693 baselineSpirvVersion,
694 maxSpirvVersion,
695 cmdLine.getOption<opt::SpirvAllow14>());
696
697 tcu::print("DONE: %d passed, %d failed, %d not supported\n", stats.numSucceeded, stats.numFailed, stats.notSupported);
698
699 return stats.numFailed == 0 ? 0 : -1;
700 }
701 catch (const std::exception& e)
702 {
703 tcu::die("%s", e.what());
704 }
705 }
706