c8699be05575692fa87cf74149d732409a874920
[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)
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
95         while (iterator.getState() != tcu::TestHierarchyIterator::STATE_FINISHED)
96         {
97                 if (iterator.getState() == tcu::TestHierarchyIterator::STATE_ENTER_NODE &&
98                         tcu::isTestNodeTypeExecutable(iterator.getNode()->getNodeType()))
99                 {
100                         const TestCase* const           testCase        = dynamic_cast<TestCase*>(iterator.getNode());
101                         const string                            casePath        = iterator.getNodePath();
102                         vk::SourceCollection            progs;
103
104                         tcu::print("%s\n", casePath.c_str());
105
106                         testCase->initPrograms(progs);
107
108                         for (vk::SourceCollection::Iterator progIter = progs.begin(); progIter != progs.end(); ++progIter)
109                         {
110                                 try
111                                 {
112                                         const vk::ProgramIdentifier                     progId          (casePath, progIter.getName());
113                                         glu::ShaderProgramInfo                          buildInfo;
114                                         const UniquePtr<vk::ProgramBinary>      binary          (vk::buildProgram(progIter.getProgram(), vk::PROGRAM_FORMAT_SPIRV, &buildInfo));
115
116                                         if (mode == BUILDMODE_BUILD)
117                                                 writer->storeProgram(progId, *binary);
118                                         else
119                                         {
120                                                 DE_ASSERT(mode == BUILDMODE_VERIFY);
121
122                                                 const UniquePtr<vk::ProgramBinary>      storedBinary    (reader->loadProgram(progId));
123
124                                                 if (binary->getSize() != storedBinary->getSize())
125                                                         throw tcu::Exception("Binary size doesn't match");
126
127                                                 if (deMemCmp(binary->getBinary(), storedBinary->getBinary(), binary->getSize()))
128                                                         throw tcu::Exception("Binary contents don't match");
129                                         }
130
131                                         tcu::print("  OK: %s\n", progIter.getName().c_str());
132                                         stats.numSucceeded += 1;
133                                 }
134                                 catch (const std::exception& e)
135                                 {
136                                         tcu::print("  ERROR: %s: %s\n", progIter.getName().c_str(), e.what());
137                                         stats.numFailed += 1;
138                                 }
139                         }
140                 }
141
142                 iterator.next();
143         }
144
145         return stats;
146 }
147
148 } // vkt
149
150 namespace opt
151 {
152
153 DE_DECLARE_COMMAND_LINE_OPT(DstPath,    std::string);
154 DE_DECLARE_COMMAND_LINE_OPT(Mode,               vkt::BuildMode);
155
156 } // opt
157
158 void registerOptions (de::cmdline::Parser& parser)
159 {
160         using de::cmdline::Option;
161         using de::cmdline::NamedValue;
162
163         static const NamedValue<vkt::BuildMode> s_modes[] =
164         {
165                 { "build",      vkt::BUILDMODE_BUILD    },
166                 { "verify",     vkt::BUILDMODE_VERIFY   }
167         };
168
169         parser << Option<opt::DstPath>  ("d", "dst-path",       "Destination path",     ".")
170                    << Option<opt::Mode>         ("m", "mode",           "Build mode",           s_modes,        "build");
171 }
172
173 int main (int argc, const char* argv[])
174 {
175         de::cmdline::CommandLine        cmdLine;
176
177         {
178                 de::cmdline::Parser             parser;
179                 registerOptions(parser);
180                 if (!parser.parse(argc, argv, &cmdLine, std::cerr))
181                 {
182                         parser.help(std::cout);
183                         return -1;
184                 }
185         }
186
187         try
188         {
189                 const tcu::CommandLine  deqpCmdLine             ("unused");
190                 tcu::DirArchive                 archive                 (".");
191                 tcu::TestLog                    log                             (deqpCmdLine.getLogFileName(), deqpCmdLine.getLogFlags());
192                 tcu::Platform                   platform;
193                 tcu::TestContext                testCtx                 (platform, archive, log, deqpCmdLine, DE_NULL);
194
195                 const vkt::BuildStats   stats                   = vkt::buildPrograms(testCtx, cmdLine.getOption<opt::DstPath>(), cmdLine.getOption<opt::Mode>());
196
197                 tcu::print("DONE: %d passed, %d failed\n", stats.numSucceeded, stats.numFailed);
198
199                 return stats.numFailed == 0 ? 0 : -1;
200         }
201         catch (const std::exception& e)
202         {
203                 tcu::die("%s", e.what());
204         }
205 }