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 44using std::vector; 45using std::string; 46using de::UniquePtr; 47using de::MovePtr; 48using de::SharedPtr; 49 50namespace vkt 51{ 52 53namespace // anonymous 54{ 55 56typedef de::SharedPtr<glu::ProgramSources> ProgramSourcesSp; 57typedef de::SharedPtr<vk::SpirVAsmSource> SpirVAsmSourceSp; 58typedef de::SharedPtr<vk::ProgramBinary> ProgramBinarySp; 59 60class Task 61{ 62public: 63 virtual void execute (void) = 0; 64}; 65 66typedef de::ThreadSafeRingBuffer<Task*> TaskQueue; 67 68class TaskExecutorThread : public de::Thread 69{ 70public: 71 TaskExecutorThread (TaskQueue& tasks) 72 : m_tasks(tasks) 73 { 74 start(); 75 } 76 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 90private: 91 TaskQueue& m_tasks; 92}; 93 94class TaskExecutor 95{ 96public: 97 TaskExecutor (deUint32 numThreads); 98 ~TaskExecutor (void); 99 100 void submit (Task* task); 101 void waitForComplete (void); 102 103private: 104 typedef de::SharedPtr<TaskExecutorThread> ExecThreadSp; 105 106 std::vector<ExecThreadSp> m_threads; 107 TaskQueue m_tasks; 108}; 109 110TaskExecutor::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 118TaskExecutor::~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 127void TaskExecutor::submit (Task* task) 128{ 129 DE_ASSERT(task); 130 m_tasks.pushFront(task); 131} 132 133class SyncTask : public Task 134{ 135public: 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 142 SyncTask (void) 143 : m_enterBarrier (DE_NULL) 144 , m_inBarrier (DE_NULL) 145 , m_leaveBarrier (DE_NULL) 146 {} 147 148 void execute (void) 149 { 150 m_enterBarrier->increment(); 151 m_inBarrier->decrement(); 152 m_leaveBarrier->increment(); 153 } 154 155private: 156 de::Semaphore* m_enterBarrier; 157 de::Semaphore* m_inBarrier; 158 de::Semaphore* m_leaveBarrier; 159}; 160 161void 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 184struct 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 206 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 {} 212 Program (void) 213 : id ("", "") 214 , buildStatus (STATUS_NOT_COMPLETED) 215 , validationStatus (STATUS_NOT_COMPLETED) 216 , validatorOptions() 217 {} 218}; 219 220void 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 243template <typename Source> 244class BuildHighLevelShaderTask : public Task 245{ 246public: 247 248 BuildHighLevelShaderTask (const Source& source, Program* program) 249 : m_source (source) 250 , m_program (program) 251 , m_commandLine (0) 252 {} 253 254 BuildHighLevelShaderTask (void) : m_program(DE_NULL) {} 255 256 void setCommandline (const tcu::CommandLine &commandLine) 257 { 258 m_commandLine = &commandLine; 259 } 260 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 284private: 285 Source m_source; 286 Program* m_program; 287 const tcu::CommandLine* m_commandLine; 288}; 289 290void 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 300class BuildSpirVAsmTask : public Task 301{ 302public: 303 BuildSpirVAsmTask (const vk::SpirVAsmSource& source, Program* program) 304 : m_source (source) 305 , m_program (program) 306 , m_commandLine (0) 307 {} 308 309 BuildSpirVAsmTask (void) : m_program(DE_NULL), m_commandLine(0) {} 310 311 void setCommandline (const tcu::CommandLine &commandLine) 312 { 313 m_commandLine = &commandLine; 314 } 315 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 338private: 339 vk::SpirVAsmSource m_source; 340 Program* m_program; 341 const tcu::CommandLine* m_commandLine; 342}; 343 344class ValidateBinaryTask : public Task 345{ 346public: 347 ValidateBinaryTask (Program* program) 348 : m_program(program) 349 {} 350 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 365private: 366 Program* m_program; 367}; 368 369tcu::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 378struct BuildStats 379{ 380 int numSucceeded; 381 int numFailed; 382 int notSupported; 383 384 BuildStats (void) 385 : numSucceeded (0) 386 , numFailed (0) 387 , notSupported (0) 388 { 389 } 390}; 391 392BuildStats 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 557namespace opt 558{ 559 560DE_DECLARE_COMMAND_LINE_OPT(DstPath, std::string); 561DE_DECLARE_COMMAND_LINE_OPT(Cases, std::string); 562DE_DECLARE_COMMAND_LINE_OPT(Validate, bool); 563DE_DECLARE_COMMAND_LINE_OPT(VulkanVersion, deUint32); 564DE_DECLARE_COMMAND_LINE_OPT(ShaderCache, bool); 565DE_DECLARE_COMMAND_LINE_OPT(ShaderCacheFilename, std::string); 566DE_DECLARE_COMMAND_LINE_OPT(ShaderCacheTruncate, bool); 567DE_DECLARE_COMMAND_LINE_OPT(SpirvOptimize, bool); 568DE_DECLARE_COMMAND_LINE_OPT(SpirvOptimizationRecipe,std::string); 569DE_DECLARE_COMMAND_LINE_OPT(SpirvAllow14, bool); 570 571static const de::cmdline::NamedValue<bool> s_enableNames[] = 572{ 573 { "enable", true }, 574 { "disable", false } 575}; 576 577void 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_API_VERSION(0, 1, 0, 0) }, 585 { "1.1", VK_MAKE_API_VERSION(0, 1, 1, 0) }, 586 { "1.2", VK_MAKE_API_VERSION(0, 1, 2, 0) }, 587 { "1.3", VK_MAKE_API_VERSION(0, 1, 3, 0) }, 588 }; 589 590 DE_STATIC_ASSERT(vk::SPIRV_VERSION_1_6 + 1 == vk::SPIRV_VERSION_LAST); 591 592 parser << Option<opt::DstPath>("d", "dst-path", "Destination path", "out") 593 << Option<opt::Cases>("n", "deqp-case", "Case path filter (works as in test binaries)") 594 << Option<opt::Validate>("v", "validate-spv", "Validate generated SPIR-V binaries") 595 << Option<opt::VulkanVersion>("t", "target-vulkan-version", "Target Vulkan version", s_vulkanVersion, "1.2") 596 << Option<opt::ShaderCache>("s", "shadercache", "Enable or disable shader cache", s_enableNames, "enable") 597 << Option<opt::ShaderCacheFilename>("r", "shadercache-filename", "Write shader cache to given file", "shadercache.bin") 598 << Option<opt::ShaderCacheTruncate>("x", "shadercache-truncate", "Truncate shader cache before running", s_enableNames, "enable") 599 << Option<opt::SpirvOptimize>("o", "deqp-optimize-spirv", "Enable optimization for SPIR-V", s_enableNames, "disable") 600 << Option<opt::SpirvOptimizationRecipe>("p","deqp-optimization-recipe", "Shader optimization recipe") 601 << Option<opt::SpirvAllow14>("e","allow-spirv-14", "Allow SPIR-V 1.4 with Vulkan 1.1"); 602} 603 604} // opt 605 606int main (int argc, const char* argv[]) 607{ 608 de::cmdline::CommandLine cmdLine; 609 tcu::CommandLine deqpCmdLine; 610 611 { 612 de::cmdline::Parser parser; 613 opt::registerOptions(parser); 614 if (!parser.parse(argc, argv, &cmdLine, std::cerr)) 615 { 616 parser.help(std::cout); 617 return -1; 618 } 619 } 620 621 { 622 vector<const char*> deqpArgv; 623 624 deqpArgv.push_back("unused"); 625 626 if (cmdLine.hasOption<opt::Cases>()) 627 { 628 deqpArgv.push_back("--deqp-case"); 629 deqpArgv.push_back(cmdLine.getOption<opt::Cases>().c_str()); 630 } 631 632 if (cmdLine.hasOption<opt::ShaderCacheFilename>()) 633 { 634 deqpArgv.push_back("--deqp-shadercache-filename"); 635 deqpArgv.push_back(cmdLine.getOption<opt::ShaderCacheFilename>().c_str()); 636 } 637 638 if (cmdLine.hasOption<opt::ShaderCache>()) 639 { 640 deqpArgv.push_back("--deqp-shadercache"); 641 if (cmdLine.getOption<opt::ShaderCache>()) 642 deqpArgv.push_back("enable"); 643 else 644 deqpArgv.push_back("disable"); 645 } 646 647 if (cmdLine.hasOption<opt::ShaderCacheTruncate>()) 648 { 649 deqpArgv.push_back("--deqp-shadercache-truncate"); 650 if (cmdLine.getOption<opt::ShaderCacheTruncate>()) 651 deqpArgv.push_back("enable"); 652 else 653 deqpArgv.push_back("disable"); 654 } 655 656 if (cmdLine.hasOption<opt::SpirvOptimize>()) 657 { 658 deqpArgv.push_back("--deqp-optimize-spirv"); 659 if (cmdLine.getOption<opt::SpirvOptimize>()) 660 deqpArgv.push_back("enable"); 661 else 662 deqpArgv.push_back("disable"); 663 } 664 665 if (cmdLine.hasOption<opt::SpirvOptimizationRecipe>()) 666 { 667 deqpArgv.push_back("--deqp-optimization-recipe"); 668 deqpArgv.push_back(cmdLine.getOption<opt::SpirvOptimizationRecipe>().c_str()); 669 } 670 671 if (!deqpCmdLine.parse((int)deqpArgv.size(), &deqpArgv[0])) 672 return -1; 673 } 674 675 try 676 { 677 tcu::DirArchive archive ("."); 678 tcu::TestLog log (deqpCmdLine.getLogFileName(), deqpCmdLine.getLogFlags()); 679 tcu::Platform platform; 680 tcu::TestContext testCtx (platform, archive, log, deqpCmdLine, DE_NULL); 681 vk::SpirvVersion baselineSpirvVersion = vk::getBaselineSpirvVersion(cmdLine.getOption<opt::VulkanVersion>()); 682 vk::SpirvVersion maxSpirvVersion = vk::getMaxSpirvVersionForGlsl(cmdLine.getOption<opt::VulkanVersion>()); 683 684 testCtx.writeSessionInfo(); 685 686 tcu::print("SPIR-V versions: baseline: %s, max supported: %s\n", 687 getSpirvVersionName(baselineSpirvVersion).c_str(), 688 getSpirvVersionName(maxSpirvVersion).c_str()); 689 690 const vkt::BuildStats stats = vkt::buildPrograms(testCtx, 691 cmdLine.getOption<opt::DstPath>(), 692 cmdLine.getOption<opt::Validate>(), 693 cmdLine.getOption<opt::VulkanVersion>(), 694 baselineSpirvVersion, 695 maxSpirvVersion, 696 cmdLine.getOption<opt::SpirvAllow14>()); 697 698 tcu::print("DONE: %d passed, %d failed, %d not supported\n", stats.numSucceeded, stats.numFailed, stats.notSupported); 699 700 return stats.numFailed == 0 ? 0 : -1; 701 } 702 catch (const std::exception& e) 703 { 704 tcu::die("%s", e.what()); 705 } 706} 707