Vulkan: Add wide-color tests
[platform/upstream/VK-GL-CTS.git] / executor / tools / xeExtractShaderPrograms.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Test Executor
3  * ------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
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 Extract shader programs from log.
22  *//*--------------------------------------------------------------------*/
23
24 #include "xeTestLogParser.hpp"
25 #include "xeTestResultParser.hpp"
26 #include "deFilePath.hpp"
27 #include "deStringUtil.hpp"
28 #include "deString.h"
29
30 #include <vector>
31 #include <string>
32 #include <cstdio>
33 #include <cstdlib>
34 #include <fstream>
35 #include <iostream>
36 #include <stdexcept>
37
38 using std::vector;
39 using std::string;
40 using std::set;
41 using std::map;
42
43 struct CommandLine
44 {
45         CommandLine (void)
46         {
47         }
48
49         string          filename;
50         string          dstPath;
51 };
52
53 static const char* getShaderTypeSuffix (const xe::ri::Shader::ShaderType shaderType)
54 {
55         switch (shaderType)
56         {
57                 case xe::ri::Shader::SHADERTYPE_VERTEX:                         return "vert";
58                 case xe::ri::Shader::SHADERTYPE_FRAGMENT:                       return "frag";
59                 case xe::ri::Shader::SHADERTYPE_GEOMETRY:                       return "geom";
60                 case xe::ri::Shader::SHADERTYPE_TESS_CONTROL:           return "tesc";
61                 case xe::ri::Shader::SHADERTYPE_TESS_EVALUATION:        return "tese";
62                 case xe::ri::Shader::SHADERTYPE_COMPUTE:                        return "comp";
63                 default:
64                         throw xe::Error("Invalid shader type");
65         }
66 }
67
68 static void writeShaderProgram (const CommandLine& cmdLine, const std::string& casePath, const xe::ri::ShaderProgram& shaderProgram, int programNdx)
69 {
70         const string basePath = string(de::FilePath::join(cmdLine.dstPath, casePath).getPath()) + "." + de::toString(programNdx);
71
72         for (int shaderNdx = 0; shaderNdx < shaderProgram.shaders.getNumItems(); shaderNdx++)
73         {
74                 const xe::ri::Shader&   shader          = dynamic_cast<const xe::ri::Shader&>(shaderProgram.shaders.getItem(shaderNdx));
75                 const string                    shaderPath      = basePath + "." + getShaderTypeSuffix(shader.shaderType);
76
77                 if (de::FilePath(shaderPath).exists())
78                         throw xe::Error("File '" + shaderPath + "' exists already");
79
80                 {
81                         std::ofstream out(shaderPath.c_str(), std::ifstream::binary|std::ifstream::out);
82
83                         if (!out.good())
84                                 throw xe::Error("Failed to open '" + shaderPath + "'");
85
86                         out.write(shader.source.source.c_str(), shader.source.source.size());
87                 }
88         }
89 }
90
91 struct StackEntry
92 {
93         const xe::ri::List*             list;
94         int                                             curNdx;
95
96         explicit StackEntry (const xe::ri::List* list_) : list(list_), curNdx(0) {}
97 };
98
99 static void extractShaderPrograms (const CommandLine& cmdLine, const std::string& casePath, const xe::TestCaseResult& result)
100 {
101         vector<StackEntry>      itemListStack;
102         int                                     programNdx              = 0;
103
104         itemListStack.push_back(StackEntry(&result.resultItems));
105
106         while (!itemListStack.empty())
107         {
108                 StackEntry& curEntry = itemListStack.back();
109
110                 if (curEntry.curNdx < curEntry.list->getNumItems())
111                 {
112                         const xe::ri::Item&     curItem = curEntry.list->getItem(curEntry.curNdx);
113                         curEntry.curNdx += 1;
114
115                         if (curItem.getType() == xe::ri::TYPE_SHADERPROGRAM)
116                         {
117                                 writeShaderProgram(cmdLine, casePath, static_cast<const xe::ri::ShaderProgram&>(curItem), programNdx);
118                                 programNdx += 1;
119                         }
120                         else if (curItem.getType() == xe::ri::TYPE_SECTION)
121                                 itemListStack.push_back(StackEntry(&static_cast<const xe::ri::Section&>(curItem).items));
122                 }
123                 else
124                         itemListStack.pop_back();
125         }
126
127         if (programNdx == 0)
128                 std::cout << "WARNING: no shader programs found in '" << casePath << "'\n";
129 }
130
131 class ShaderProgramExtractHandler : public xe::TestLogHandler
132 {
133 public:
134         ShaderProgramExtractHandler (const CommandLine& cmdLine)
135                 : m_cmdLine(cmdLine)
136         {
137         }
138
139         void setSessionInfo (const xe::SessionInfo&)
140         {
141                 // Ignored.
142         }
143
144         xe::TestCaseResultPtr startTestCaseResult (const char* casePath)
145         {
146                 return xe::TestCaseResultPtr(new xe::TestCaseResultData(casePath));
147         }
148
149         void testCaseResultUpdated (const xe::TestCaseResultPtr&)
150         {
151                 // Ignored.
152         }
153
154         void testCaseResultComplete (const xe::TestCaseResultPtr& caseData)
155         {
156                 if (caseData->getDataSize() > 0)
157                 {
158                         xe::TestCaseResult                                      fullResult;
159                         xe::TestResultParser::ParseResult       parseResult;
160
161                         m_testResultParser.init(&fullResult);
162                         parseResult = m_testResultParser.parse(caseData->getData(), caseData->getDataSize());
163                         DE_UNREF(parseResult);
164
165                         extractShaderPrograms(m_cmdLine, caseData->getTestCasePath(), fullResult);
166                 }
167         }
168
169 private:
170         const CommandLine&              m_cmdLine;
171         xe::TestResultParser    m_testResultParser;
172 };
173
174 static void extractShaderProgramsFromLogFile (const CommandLine& cmdLine)
175 {
176         std::ifstream                                   in                              (cmdLine.filename.c_str(), std::ifstream::binary|std::ifstream::in);
177         ShaderProgramExtractHandler             resultHandler   (cmdLine);
178         xe::TestLogParser                               parser                  (&resultHandler);
179         deUint8                                                 buf                             [1024];
180         int                                                             numRead                 = 0;
181
182         if (!in.good())
183                 throw std::runtime_error(string("Failed to open '") + cmdLine.filename + "'");
184
185         for (;;)
186         {
187                 in.read((char*)&buf[0], DE_LENGTH_OF_ARRAY(buf));
188                 numRead = (int)in.gcount();
189
190                 if (numRead <= 0)
191                         break;
192
193                 parser.parse(&buf[0], numRead);
194         }
195
196         in.close();
197 }
198
199 static void printHelp (const char* binName)
200 {
201         printf("%s: [filename] [dst path (optional)]\n", binName);
202 }
203
204 static bool parseCommandLine (CommandLine& cmdLine, int argc, const char* const* argv)
205 {
206         for (int argNdx = 1; argNdx < argc; argNdx++)
207         {
208                 const char* arg = argv[argNdx];
209
210                 if (!deStringBeginsWith(arg, "--"))
211                 {
212                         if (cmdLine.filename.empty())
213                                 cmdLine.filename = arg;
214                         else if (cmdLine.dstPath.empty())
215                                 cmdLine.dstPath = arg;
216                         else
217                                 return false;
218                 }
219                 else
220                         return false;
221         }
222
223         if (cmdLine.filename.empty())
224                 return false;
225
226         return true;
227 }
228
229 int main (int argc, const char* const* argv)
230 {
231         try
232         {
233                 CommandLine cmdLine;
234
235                 if (!parseCommandLine(cmdLine, argc, argv))
236                 {
237                         printHelp(argv[0]);
238                         return -1;
239                 }
240
241                 extractShaderProgramsFromLogFile(cmdLine);
242         }
243         catch (const std::exception& e)
244         {
245                 printf("FATAL ERROR: %s\n", e.what());
246                 return -1;
247         }
248
249         return 0;
250 }