blob: fcaf20070f7810105057f0a66d062b5528970361 [file] [log] [blame]
Jarkko Poyry3c827362014-09-02 11:48:52 +03001/*-------------------------------------------------------------------------
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
38using std::vector;
39using std::string;
40using std::set;
41using std::map;
42
43struct CommandLine
44{
45 CommandLine (void)
46 {
47 }
48
49 string filename;
50 string dstPath;
51};
52
53static 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
68static 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
91struct 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
99static 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
131class ShaderProgramExtractHandler : public xe::TestLogHandler
132{
133public:
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
169private:
170 const CommandLine& m_cmdLine;
171 xe::TestResultParser m_testResultParser;
172};
173
174static 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
199static void printHelp (const char* binName)
200{
201 printf("%s: [filename] [dst path (optional)]\n", binName);
202}
203
204static 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
229int 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}