1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 Google Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and/or associated documentation files (the
9 * "Materials"), to deal in the Materials without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Materials, and to
12 * permit persons to whom the Materials are furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice(s) and this permission notice shall be
16 * included in all copies or substantial portions of the Materials.
18 * The Materials are Confidential Information as defined by the
19 * Khronos Membership Agreement until designated non-confidential by
20 * Khronos, at which point this condition clause shall be removed.
22 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
32 * \brief Utility for pre-compiling source programs to SPIR-V
33 *//*--------------------------------------------------------------------*/
35 #include "tcuDefs.hpp"
36 #include "tcuCommandLine.hpp"
37 #include "tcuPlatform.hpp"
38 #include "tcuResource.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuTestHierarchyIterator.hpp"
41 #include "deUniquePtr.hpp"
42 #include "vkPrograms.hpp"
43 #include "vkBinaryRegistry.hpp"
44 #include "vktTestCase.hpp"
45 #include "vktTestPackage.hpp"
46 #include "deUniquePtr.hpp"
47 #include "deCommandLine.hpp"
58 tcu::TestPackageRoot* createRoot (tcu::TestContext& testCtx)
60 vector<tcu::TestNode*> children;
61 children.push_back(new TestPackage(testCtx));
62 return new tcu::TestPackageRoot(testCtx, children);
85 BuildStats buildPrograms (tcu::TestContext& testCtx, const std::string& dstPath, BuildMode mode, bool verbose)
87 const UniquePtr<tcu::TestPackageRoot> root (createRoot(testCtx));
88 tcu::DefaultHierarchyInflater inflater (testCtx);
89 tcu::TestHierarchyIterator iterator (*root, inflater, testCtx.getCommandLine());
90 const tcu::DirArchive srcArchive (dstPath.c_str());
91 UniquePtr<vk::BinaryRegistryWriter> writer (mode == BUILDMODE_BUILD ? new vk::BinaryRegistryWriter(dstPath) : DE_NULL);
92 UniquePtr<vk::BinaryRegistryReader> reader (mode == BUILDMODE_VERIFY ? new vk::BinaryRegistryReader(srcArchive, "") : DE_NULL);
94 const bool printLogs = verbose;
96 while (iterator.getState() != tcu::TestHierarchyIterator::STATE_FINISHED)
98 if (iterator.getState() == tcu::TestHierarchyIterator::STATE_ENTER_NODE &&
99 tcu::isTestNodeTypeExecutable(iterator.getNode()->getNodeType()))
101 const TestCase* const testCase = dynamic_cast<TestCase*>(iterator.getNode());
102 const string casePath = iterator.getNodePath();
103 vk::SourceCollection progs;
105 tcu::print("%s\n", casePath.c_str());
107 testCase->initPrograms(progs);
109 for (vk::SourceCollection::Iterator progIter = progs.begin(); progIter != progs.end(); ++progIter)
111 glu::ShaderProgramInfo buildInfo;
115 const vk::ProgramIdentifier progId (casePath, progIter.getName());
116 const UniquePtr<vk::ProgramBinary> binary (vk::buildProgram(progIter.getProgram(), vk::PROGRAM_FORMAT_SPIRV, &buildInfo));
118 if (mode == BUILDMODE_BUILD)
119 writer->storeProgram(progId, *binary);
122 DE_ASSERT(mode == BUILDMODE_VERIFY);
124 const UniquePtr<vk::ProgramBinary> storedBinary (reader->loadProgram(progId));
126 if (binary->getSize() != storedBinary->getSize())
127 throw tcu::Exception("Binary size doesn't match");
129 if (deMemCmp(binary->getBinary(), storedBinary->getBinary(), binary->getSize()))
130 throw tcu::Exception("Binary contents don't match");
133 tcu::print(" OK: %s\n", progIter.getName().c_str());
134 stats.numSucceeded += 1;
136 catch (const std::exception& e)
138 tcu::print(" ERROR: %s: %s\n", progIter.getName().c_str(), e.what());
142 for (size_t shaderNdx = 0; shaderNdx < buildInfo.shaders.size(); shaderNdx++)
144 const glu::ShaderInfo& shaderInfo = buildInfo.shaders[shaderNdx];
145 const char* const shaderName = getShaderTypeName(shaderInfo.type);
147 tcu::print("%s source:\n---\n%s\n---\n", shaderName, shaderInfo.source.c_str());
148 tcu::print("%s compile log:\n---\n%s\n---\n", shaderName, shaderInfo.infoLog.c_str());
152 stats.numFailed += 1;
168 DE_DECLARE_COMMAND_LINE_OPT(DstPath, std::string);
169 DE_DECLARE_COMMAND_LINE_OPT(Mode, vkt::BuildMode);
170 DE_DECLARE_COMMAND_LINE_OPT(Verbose, bool);
174 void registerOptions (de::cmdline::Parser& parser)
176 using de::cmdline::Option;
177 using de::cmdline::NamedValue;
179 static const NamedValue<vkt::BuildMode> s_modes[] =
181 { "build", vkt::BUILDMODE_BUILD },
182 { "verify", vkt::BUILDMODE_VERIFY }
185 parser << Option<opt::DstPath> ("d", "dst-path", "Destination path", "out")
186 << Option<opt::Mode> ("m", "mode", "Build mode", s_modes, "build")
187 << Option<opt::Verbose> ("v", "verbose", "Verbose output");
190 int main (int argc, const char* argv[])
192 de::cmdline::CommandLine cmdLine;
195 de::cmdline::Parser parser;
196 registerOptions(parser);
197 if (!parser.parse(argc, argv, &cmdLine, std::cerr))
199 parser.help(std::cout);
206 const tcu::CommandLine deqpCmdLine ("unused");
207 tcu::DirArchive archive (".");
208 tcu::TestLog log (deqpCmdLine.getLogFileName(), deqpCmdLine.getLogFlags());
209 tcu::Platform platform;
210 tcu::TestContext testCtx (platform, archive, log, deqpCmdLine, DE_NULL);
212 const vkt::BuildStats stats = vkt::buildPrograms(testCtx,
213 cmdLine.getOption<opt::DstPath>(),
214 cmdLine.getOption<opt::Mode>(),
215 cmdLine.getOption<opt::Verbose>());
217 tcu::print("DONE: %d passed, %d failed\n", stats.numSucceeded, stats.numFailed);
219 return stats.numFailed == 0 ? 0 : -1;
221 catch (const std::exception& e)
223 tcu::die("%s", e.what());