Add --verbose option to vk-build-programs
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / vktBuildPrograms.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 Google Inc.
6  *
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:
14  *
15  * The above copyright notice(s) and this permission notice shall be
16  * included in all copies or substantial portions of the Materials.
17  *
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.
21  *
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.
29  *
30  *//*!
31  * \file
32  * \brief Utility for pre-compiling source programs to SPIR-V
33  *//*--------------------------------------------------------------------*/
34
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"
48
49 #include <iostream>
50
51 namespace vkt
52 {
53
54 using std::vector;
55 using std::string;
56 using de::UniquePtr;
57
58 tcu::TestPackageRoot* createRoot (tcu::TestContext& testCtx)
59 {
60         vector<tcu::TestNode*>  children;
61         children.push_back(new TestPackage(testCtx));
62         return new tcu::TestPackageRoot(testCtx, children);
63 }
64
65 enum BuildMode
66 {
67         BUILDMODE_BUILD = 0,
68         BUILDMODE_VERIFY,
69
70         BUILDMODE_LAST
71 };
72
73 struct BuildStats
74 {
75         int             numSucceeded;
76         int             numFailed;
77
78         BuildStats (void)
79                 : numSucceeded  (0)
80                 , numFailed             (0)
81         {
82         }
83 };
84
85 BuildStats buildPrograms (tcu::TestContext& testCtx, const std::string& dstPath, BuildMode mode, bool verbose)
86 {
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);
93         BuildStats                                                              stats;
94         const bool                                                              printLogs       = verbose;
95
96         while (iterator.getState() != tcu::TestHierarchyIterator::STATE_FINISHED)
97         {
98                 if (iterator.getState() == tcu::TestHierarchyIterator::STATE_ENTER_NODE &&
99                         tcu::isTestNodeTypeExecutable(iterator.getNode()->getNodeType()))
100                 {
101                         const TestCase* const           testCase        = dynamic_cast<TestCase*>(iterator.getNode());
102                         const string                            casePath        = iterator.getNodePath();
103                         vk::SourceCollection            progs;
104
105                         tcu::print("%s\n", casePath.c_str());
106
107                         testCase->initPrograms(progs);
108
109                         for (vk::SourceCollection::Iterator progIter = progs.begin(); progIter != progs.end(); ++progIter)
110                         {
111                                 glu::ShaderProgramInfo  buildInfo;
112
113                                 try
114                                 {
115                                         const vk::ProgramIdentifier                     progId          (casePath, progIter.getName());
116                                         const UniquePtr<vk::ProgramBinary>      binary          (vk::buildProgram(progIter.getProgram(), vk::PROGRAM_FORMAT_SPIRV, &buildInfo));
117
118                                         if (mode == BUILDMODE_BUILD)
119                                                 writer->storeProgram(progId, *binary);
120                                         else
121                                         {
122                                                 DE_ASSERT(mode == BUILDMODE_VERIFY);
123
124                                                 const UniquePtr<vk::ProgramBinary>      storedBinary    (reader->loadProgram(progId));
125
126                                                 if (binary->getSize() != storedBinary->getSize())
127                                                         throw tcu::Exception("Binary size doesn't match");
128
129                                                 if (deMemCmp(binary->getBinary(), storedBinary->getBinary(), binary->getSize()))
130                                                         throw tcu::Exception("Binary contents don't match");
131                                         }
132
133                                         tcu::print("  OK: %s\n", progIter.getName().c_str());
134                                         stats.numSucceeded += 1;
135                                 }
136                                 catch (const std::exception& e)
137                                 {
138                                         tcu::print("  ERROR: %s: %s\n", progIter.getName().c_str(), e.what());
139
140                                         if (printLogs)
141                                         {
142                                                 for (size_t shaderNdx = 0; shaderNdx < buildInfo.shaders.size(); shaderNdx++)
143                                                 {
144                                                         const glu::ShaderInfo&  shaderInfo      = buildInfo.shaders[shaderNdx];
145                                                         const char* const               shaderName      = getShaderTypeName(shaderInfo.type);
146
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());
149                                                 }
150                                         }
151
152                                         stats.numFailed += 1;
153                                 }
154                         }
155                 }
156
157                 iterator.next();
158         }
159
160         return stats;
161 }
162
163 } // vkt
164
165 namespace opt
166 {
167
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);
171
172 } // opt
173
174 void registerOptions (de::cmdline::Parser& parser)
175 {
176         using de::cmdline::Option;
177         using de::cmdline::NamedValue;
178
179         static const NamedValue<vkt::BuildMode> s_modes[] =
180         {
181                 { "build",      vkt::BUILDMODE_BUILD    },
182                 { "verify",     vkt::BUILDMODE_VERIFY   }
183         };
184
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");
188 }
189
190 int main (int argc, const char* argv[])
191 {
192         de::cmdline::CommandLine        cmdLine;
193
194         {
195                 de::cmdline::Parser             parser;
196                 registerOptions(parser);
197                 if (!parser.parse(argc, argv, &cmdLine, std::cerr))
198                 {
199                         parser.help(std::cout);
200                         return -1;
201                 }
202         }
203
204         try
205         {
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);
211
212                 const vkt::BuildStats   stats                   = vkt::buildPrograms(testCtx,
213                                                                                                                                          cmdLine.getOption<opt::DstPath>(),
214                                                                                                                                          cmdLine.getOption<opt::Mode>(),
215                                                                                                                                          cmdLine.getOption<opt::Verbose>());
216
217                 tcu::print("DONE: %d passed, %d failed\n", stats.numSucceeded, stats.numFailed);
218
219                 return stats.numFailed == 0 ? 0 : -1;
220         }
221         catch (const std::exception& e)
222         {
223                 tcu::die("%s", e.what());
224         }
225 }